Merge "[pm/metrics] add dexopt latency to the metrics" into udc-dev
diff --git a/apct-tests/perftests/core/OWNERS b/apct-tests/perftests/core/OWNERS
index 8fb057d..6abab6e 100644
--- a/apct-tests/perftests/core/OWNERS
+++ b/apct-tests/perftests/core/OWNERS
@@ -3,4 +3,12 @@
 
 # Bug component: 568761
 per-file /apct-tests/perftests/core/res/* = felkachang@google.com,zyy@google.com
+per-file /apct-tests/perftests/core/res/* = file:/core/java/android/content/om/OWNERS
+per-file /apct-tests/perftests/core/src/android/content/res/* = felkachang@google.com
+per-file /apct-tests/perftests/core/src/android/content/res/* = file:/core/java/android/content/res/OWNERS
+
+
+# Bug component: 568631
+per-file /apct-tests/perftests/core/src/android/content/om/* = felkachang@google.com
+per-file /apct-tests/perftests/core/src/android/content/om/* = file:/core/java/android/content/om/OWNERS
 
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index f6c18d6..7f02cb3 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -397,18 +397,11 @@
     public static final int FLAG_EXPEDITED = 1 << 4;
 
     /**
-     * Whether it's a data transfer job or not.
-     *
-     * @hide
-     */
-    public static final int FLAG_DATA_TRANSFER = 1 << 5;
-
-    /**
      * Whether it's a user initiated job or not.
      *
      * @hide
      */
-    public static final int FLAG_USER_INITIATED = 1 << 6;
+    public static final int FLAG_USER_INITIATED = 1 << 5;
 
     /**
      * @hide
@@ -738,13 +731,6 @@
     }
 
     /**
-     * @see JobInfo.Builder#setDataTransfer(boolean)
-     */
-    public boolean isDataTransfer() {
-        return (flags & FLAG_DATA_TRANSFER) != 0;
-    }
-
-    /**
      * @see JobInfo.Builder#setUserInitiated(boolean)
      */
     public boolean isUserInitiated() {
@@ -1850,39 +1836,6 @@
         }
 
         /**
-         * Indicates that this job will be used to transfer data to or from a remote server. The
-         * system could attempt to run a data transfer job longer than a regular job if the data
-         * being transferred is potentially very large and can take a long time to complete.
-         *
-         * <p>
-         * You must provide an estimate of the payload size via
-         * {@link #setEstimatedNetworkBytes(long, long)} when scheduling the job or use
-         * {@link JobService#updateEstimatedNetworkBytes(JobParameters, long, long)} or
-         * {@link JobService#updateEstimatedNetworkBytes(JobParameters, JobWorkItem, long, long)}
-         * shortly after the job starts.
-         *
-         * <p>
-         * For user-initiated transfers that must be started immediately, call
-         * {@link #setUserInitiated(boolean) setUserInitiated(true)}. Otherwise, the system may
-         * defer the job to a more opportune time.
-         *
-         * <p>
-         * If you want to perform more than one data transfer job, consider enqueuing multiple
-         * {@link JobWorkItem JobWorkItems} along with {@link #setDataTransfer(boolean)}.
-         *
-         * @see JobInfo#isDataTransfer()
-         */
-        @NonNull
-        public Builder setDataTransfer(boolean dataTransfer) {
-            if (dataTransfer) {
-                mFlags |= FLAG_DATA_TRANSFER;
-            } else {
-                mFlags &= (~FLAG_DATA_TRANSFER);
-            }
-            return this;
-        }
-
-        /**
          * Indicates that this job is being scheduled to fulfill an explicit user request.
          * As such, user-initiated jobs can only be scheduled when the app is in the foreground
          * or in a state where launching an activity is allowed, as defined
@@ -1909,6 +1862,11 @@
          * {@link SecurityException}.
          *
          * <p>
+         * In {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE}, user-initiated jobs can only
+         * be used for network data transfers. As such, they must specify a required network via
+         * {@link #setRequiredNetwork(NetworkRequest)} or {@link #setRequiredNetworkType(int)}.
+         *
+         * <p>
          * These jobs will not be subject to quotas and will be started immediately once scheduled
          * if all constraints are met and the device system health allows for additional tasks.
          *
@@ -2179,10 +2137,6 @@
             if (isPeriodic) {
                 throw new IllegalArgumentException("An expedited job cannot be periodic");
             }
-            if ((flags & FLAG_DATA_TRANSFER) != 0) {
-                throw new IllegalArgumentException(
-                        "An expedited job cannot also be a data transfer job");
-            }
             if (isUserInitiated) {
                 throw new IllegalArgumentException("An expedited job cannot be user-initiated");
             }
@@ -2202,24 +2156,6 @@
             }
         }
 
-        if ((flags & FLAG_DATA_TRANSFER) != 0) {
-            if (backoffPolicy == BACKOFF_POLICY_LINEAR) {
-                throw new IllegalArgumentException(
-                        "A data transfer job cannot have a linear backoff policy.");
-            }
-            if (hasLateConstraint) {
-                throw new IllegalArgumentException("A data transfer job cannot have a deadline");
-            }
-            if ((flags & FLAG_PREFETCH) != 0) {
-                throw new IllegalArgumentException(
-                        "A data transfer job cannot also be a prefetch job");
-            }
-            if (networkRequest == null) {
-                throw new IllegalArgumentException(
-                        "A data transfer job must specify a valid network type");
-            }
-        }
-
         if (isUserInitiated) {
             if (hasEarlyConstraint) {
                 throw new IllegalArgumentException("A user-initiated job cannot have a time delay");
@@ -2245,6 +2181,15 @@
                 throw new IllegalArgumentException(
                         "Can't call addTriggerContentUri() on a user-initiated job");
             }
+            // UIDTs
+            if (networkRequest == null) {
+                throw new IllegalArgumentException(
+                        "A user-initaited data transfer job must specify a valid network type");
+            }
+            if (backoffPolicy == BACKOFF_POLICY_LINEAR) {
+                throw new IllegalArgumentException(
+                        "A user-initiated data transfer job cannot have a linear backoff policy.");
+            }
         }
     }
 
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 bf3789f..0af191a 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -478,8 +478,6 @@
                         case Constants.KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS:
                         case Constants.KEY_RUNTIME_MIN_GUARANTEE_MS:
                         case Constants.KEY_RUNTIME_MIN_EJ_GUARANTEE_MS:
-                        case Constants.KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS:
-                        case Constants.KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS:
                         case Constants.KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS:
                         case Constants.KEY_RUNTIME_USER_INITIATED_LIMIT_MS:
                         case Constants.KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR:
@@ -574,10 +572,6 @@
                 "runtime_free_quota_max_limit_ms";
         private static final String KEY_RUNTIME_MIN_GUARANTEE_MS = "runtime_min_guarantee_ms";
         private static final String KEY_RUNTIME_MIN_EJ_GUARANTEE_MS = "runtime_min_ej_guarantee_ms";
-        private static final String KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
-                "runtime_min_data_transfer_guarantee_ms";
-        private static final String KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS =
-                "runtime_data_transfer_limit_ms";
         private static final String KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS =
                 "runtime_min_user_initiated_guarantee_ms";
         private static final String KEY_RUNTIME_USER_INITIATED_LIMIT_MS =
@@ -616,10 +610,6 @@
         public static final long DEFAULT_RUNTIME_MIN_GUARANTEE_MS = 10 * MINUTE_IN_MILLIS;
         @VisibleForTesting
         public static final long DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS = 3 * MINUTE_IN_MILLIS;
-        public static final long DEFAULT_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
-                DEFAULT_RUNTIME_MIN_GUARANTEE_MS;
-        public static final long DEFAULT_RUNTIME_DATA_TRANSFER_LIMIT_MS =
-                DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
         public static final long DEFAULT_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS =
                 Math.max(10 * MINUTE_IN_MILLIS, DEFAULT_RUNTIME_MIN_GUARANTEE_MS);
         public static final long DEFAULT_RUNTIME_USER_INITIATED_LIMIT_MS =
@@ -739,18 +729,6 @@
         public long RUNTIME_MIN_EJ_GUARANTEE_MS = DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS;
 
         /**
-         * The minimum amount of time we try to guarantee normal data transfer jobs will run for.
-         */
-        public long RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
-                DEFAULT_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS;
-
-        /**
-         * The maximum amount of time we will let a normal data transfer job run for. This will only
-         * apply if there are no other limits that apply to the specific data transfer job.
-         */
-        public long RUNTIME_DATA_TRANSFER_LIMIT_MS = DEFAULT_RUNTIME_DATA_TRANSFER_LIMIT_MS;
-
-        /**
          * The minimum amount of time we try to guarantee normal user-initiated jobs will run for.
          */
         public long RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS =
@@ -885,8 +863,6 @@
                     KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                     KEY_RUNTIME_MIN_GUARANTEE_MS, KEY_RUNTIME_MIN_EJ_GUARANTEE_MS,
                     KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR,
-                    KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
-                    KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS,
                     KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
                     KEY_RUNTIME_USER_INITIATED_LIMIT_MS,
                     KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS,
@@ -904,17 +880,6 @@
                     properties.getLong(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                             DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS));
             // Make sure min runtime is at least as long as regular jobs.
-            RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS = Math.max(RUNTIME_MIN_GUARANTEE_MS,
-                    properties.getLong(
-                            KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
-                            DEFAULT_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS));
-            // Max limit should be at least the min guarantee AND the free quota.
-            RUNTIME_DATA_TRANSFER_LIMIT_MS = Math.max(RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
-                    Math.max(RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
-                            properties.getLong(
-                                    KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS,
-                                    DEFAULT_RUNTIME_DATA_TRANSFER_LIMIT_MS)));
-            // Make sure min runtime is at least as long as regular jobs.
             RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS = Math.max(RUNTIME_MIN_GUARANTEE_MS,
                     properties.getLong(
                             KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
@@ -993,10 +958,6 @@
             pw.print(KEY_RUNTIME_MIN_EJ_GUARANTEE_MS, RUNTIME_MIN_EJ_GUARANTEE_MS).println();
             pw.print(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
                     .println();
-            pw.print(KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
-                    RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS).println();
-            pw.print(KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS,
-                    RUNTIME_DATA_TRANSFER_LIMIT_MS).println();
             pw.print(KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
                     RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS).println();
             pw.print(KEY_RUNTIME_USER_INITIATED_LIMIT_MS,
@@ -3291,7 +3252,7 @@
             if (job.shouldTreatAsUserInitiatedJob()
                     && checkRunUserInitiatedJobsPermission(
                             job.getSourceUid(), job.getSourcePackageName())) {
-                if (job.getJob().isDataTransfer()) {
+                if (job.getJob().getRequiredNetwork() != null) { // UI+DT
                     final long estimatedTransferTimeMs =
                             mConnectivityController.getEstimatedTransferTimeMs(job);
                     if (estimatedTransferTimeMs == ConnectivityController.UNKNOWN_TIME) {
@@ -3308,9 +3269,6 @@
                             ));
                 }
                 return mConstants.RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS;
-            } else if (job.getJob().isDataTransfer()) {
-                // For now, don't increase a bg data transfer's minimum guarantee.
-                return mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS;
             } else if (job.shouldTreatAsExpeditedJob()) {
                 // Don't guarantee RESTRICTED jobs more than 5 minutes.
                 return job.getEffectiveStandbyBucket() != RESTRICTED_INDEX
@@ -3328,7 +3286,7 @@
             final boolean allowLongerJob = job.shouldTreatAsUserInitiatedJob()
                     && checkRunUserInitiatedJobsPermission(
                             job.getSourceUid(), job.getSourcePackageName());
-            if (job.getJob().isDataTransfer() && allowLongerJob) { // UI+DT
+            if (job.getJob().getRequiredNetwork() != null && allowLongerJob) { // UI+DT
                 return mConstants.RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS;
             }
             if (allowLongerJob) { // UI with LRJ permission
@@ -3337,9 +3295,6 @@
             if (job.shouldTreatAsUserInitiatedJob()) {
                 return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
             }
-            if (job.getJob().isDataTransfer()) {
-                return mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS;
-            }
             return Math.min(mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                     mConstants.USE_TARE_POLICY
                             ? mTareController.getMaxJobExecutionTimeMsLocked(job)
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 29ab455..e60ed4a 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -727,8 +727,11 @@
                     // Exception-throwing-can down the road to JobParameters.completeWork >:(
                     return true;
                 }
-                mService.mJobs.touchJob(mRunningJob);
-                return mRunningJob.completeWorkLocked(workId);
+                if (mRunningJob.completeWorkLocked(workId)) {
+                    mService.mJobs.touchJob(mRunningJob);
+                    return true;
+                }
+                return false;
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
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 1971a11..537a670 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
@@ -828,6 +828,10 @@
         }
     }
 
+    /**
+     * Returns {@code true} if the JobWorkItem queue was updated,
+     * and {@code false} if nothing changed.
+     */
     public boolean completeWorkLocked(int workId) {
         if (executingWork != null) {
             final int N = executingWork.size();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
index 9ada8dc..47b7e13 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/CarIdlenessTracker.java
@@ -24,6 +24,7 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.server.JobSchedulerBackgroundThread;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
@@ -50,7 +51,7 @@
     public static final String ACTION_UNFORCE_IDLE = "com.android.server.jobscheduler.UNFORCE_IDLE";
 
     // After construction, mutations of idle/screen-on state will only happen
-    // on the main looper thread, either in onReceive() or in an alarm callback.
+    // on the JobScheduler thread, either in onReceive() or in an alarm callback.
     private boolean mIdle;
     private boolean mGarageModeOn;
     private boolean mForced;
@@ -90,7 +91,7 @@
         filter.addAction(ACTION_UNFORCE_IDLE);
         filter.addAction(ActivityManagerService.ACTION_TRIGGER_IDLE);
 
-        context.registerReceiver(this, filter);
+        context.registerReceiver(this, filter, null, JobSchedulerBackgroundThread.getHandler());
     }
 
     @Override
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
index 140cca6..15d6766 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/idle/DeviceIdlenessTracker.java
@@ -31,6 +31,7 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.server.JobSchedulerBackgroundThread;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
@@ -47,8 +48,8 @@
     private AlarmManager mAlarm;
     private PowerManager mPowerManager;
 
-    // After construction, mutations of idle/screen-on state will only happen
-    // on the main looper thread, either in onReceive() or in an alarm callback.
+    // After construction, mutations of idle/screen-on/projection states will only happen
+    // on the JobScheduler thread, either in onReceive(), in an alarm callback, or in on.*Changed.
     private long mInactivityIdleThreshold;
     private long mIdleWindowSlop;
     private boolean mIdle;
@@ -101,12 +102,10 @@
         filter.addAction(Intent.ACTION_DOCK_IDLE);
         filter.addAction(Intent.ACTION_DOCK_ACTIVE);
 
-        context.registerReceiver(this, filter);
+        context.registerReceiver(this, filter, null, JobSchedulerBackgroundThread.getHandler());
 
-        // TODO(b/172579710): Move the callbacks off the main executor and on to
-        //  JobSchedulerBackgroundThread.getExecutor() once synchronization is fixed in this class.
         context.getSystemService(UiModeManager.class).addOnProjectionStateChangedListener(
-                UiModeManager.PROJECTION_TYPE_ALL, context.getMainExecutor(),
+                UiModeManager.PROJECTION_TYPE_ALL, JobSchedulerBackgroundThread.getExecutor(),
                 mOnProjectionStateChangedListener);
     }
 
@@ -226,7 +225,8 @@
                 Slog.v(TAG, "Scheduling idle : " + reason + " now:" + nowElapsed + " when=" + when);
             }
             mAlarm.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                    when, mIdleWindowSlop, "JS idleness", mIdleAlarmListener, null);
+                    when, mIdleWindowSlop, "JS idleness",
+                    JobSchedulerBackgroundThread.getExecutor(), mIdleAlarmListener);
         }
     }
 
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
index a6a3aaf..6a4a52a 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
+++ b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
@@ -4,6 +4,7 @@
       "name": "CtsUsageStatsTestCases",
       "options": [
         {"include-filter": "android.app.usage.cts.UsageStatsTest"},
+        {"include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"},
         {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
         {"exclude-annotation": "androidx.test.filters.FlakyTest"},
         {"exclude-annotation": "androidx.test.filters.MediumTest"},
@@ -19,18 +20,6 @@
       ]
     }
   ],
-  "presubmit-large": [
-    {
-      "name": "CtsUsageStatsTestCases",
-      "options": [
-        {"include-filter": "android.app.usage.cts.BroadcastResponseStatsTest"},
-        {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
-        {"exclude-annotation": "androidx.test.filters.FlakyTest"},
-        {"exclude-annotation": "androidx.test.filters.MediumTest"},
-        {"exclude-annotation": "androidx.test.filters.LargeTest"}
-      ]
-    }
-  ],
   "postsubmit": [
     {
       "name": "CtsUsageStatsTestCases"
diff --git a/core/api/current.txt b/core/api/current.txt
index 2161186..0536947 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6784,7 +6784,7 @@
     method public boolean areNotificationsEnabled();
     method public boolean areNotificationsPaused();
     method public boolean canNotifyAsPackage(@NonNull String);
-    method public boolean canSendFullScreenIntent();
+    method public boolean canUseFullScreenIntent();
     method public void cancel(int);
     method public void cancel(@Nullable String, int);
     method public void cancelAll();
@@ -7269,6 +7269,13 @@
     method public void onSharedElementsReady();
   }
 
+  public final class StartForegroundCalledOnStoppedServiceException extends java.lang.IllegalStateException implements android.os.Parcelable {
+    ctor public StartForegroundCalledOnStoppedServiceException(@NonNull String);
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.app.StartForegroundCalledOnStoppedServiceException> CREATOR;
+  }
+
   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>);
@@ -8733,7 +8740,6 @@
     method public long getTriggerContentMaxDelay();
     method public long getTriggerContentUpdateDelay();
     method @Nullable public android.app.job.JobInfo.TriggerContentUri[] getTriggerContentUris();
-    method public boolean isDataTransfer();
     method public boolean isExpedited();
     method public boolean isImportantWhileForeground();
     method public boolean isPeriodic();
@@ -8770,7 +8776,6 @@
     method public android.app.job.JobInfo build();
     method public android.app.job.JobInfo.Builder setBackoffCriteria(long, int);
     method public android.app.job.JobInfo.Builder setClipData(@Nullable android.content.ClipData, int);
-    method @NonNull public android.app.job.JobInfo.Builder setDataTransfer(boolean);
     method public android.app.job.JobInfo.Builder setEstimatedNetworkBytes(long, long);
     method @NonNull public android.app.job.JobInfo.Builder setExpedited(boolean);
     method public android.app.job.JobInfo.Builder setExtras(@NonNull android.os.PersistableBundle);
@@ -9576,8 +9581,6 @@
 
   public final class VirtualDeviceManager {
     method @NonNull public java.util.List<android.companion.virtual.VirtualDevice> getVirtualDevices();
-    field public static final int DEVICE_ID_DEFAULT = 0; // 0x0
-    field public static final int DEVICE_ID_INVALID = -1; // 0xffffffff
   }
 
 }
@@ -10354,6 +10357,8 @@
     field public static final int CONTEXT_RESTRICTED = 4; // 0x4
     field public static final String CREDENTIAL_SERVICE = "credential";
     field public static final String CROSS_PROFILE_APPS_SERVICE = "crossprofileapps";
+    field public static final int DEVICE_ID_DEFAULT = 0; // 0x0
+    field public static final int DEVICE_ID_INVALID = -1; // 0xffffffff
     field public static final String DEVICE_LOCK_SERVICE = "device_lock";
     field public static final String DEVICE_POLICY_SERVICE = "device_policy";
     field public static final String DISPLAY_HASH_SERVICE = "display_hash";
@@ -12448,7 +12453,7 @@
     method @Nullable public abstract android.graphics.drawable.Drawable getActivityBanner(@NonNull android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract android.graphics.drawable.Drawable getActivityIcon(@NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract android.graphics.drawable.Drawable getActivityIcon(@NonNull android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated @NonNull public abstract android.content.pm.ActivityInfo getActivityInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @NonNull public abstract android.content.pm.ActivityInfo getActivityInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.pm.ActivityInfo getActivityInfo(@NonNull android.content.ComponentName, @NonNull android.content.pm.PackageManager.ComponentInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Nullable public abstract android.graphics.drawable.Drawable getActivityLogo(@NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Nullable public abstract android.graphics.drawable.Drawable getActivityLogo(@NonNull android.content.Intent) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -12458,7 +12463,7 @@
     method public abstract int getApplicationEnabledSetting(@NonNull String);
     method @NonNull public abstract android.graphics.drawable.Drawable getApplicationIcon(@NonNull android.content.pm.ApplicationInfo);
     method @NonNull public abstract android.graphics.drawable.Drawable getApplicationIcon(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated @NonNull public abstract android.content.pm.ApplicationInfo getApplicationInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @NonNull public abstract android.content.pm.ApplicationInfo getApplicationInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.pm.ApplicationInfo getApplicationInfo(@NonNull String, @NonNull android.content.pm.PackageManager.ApplicationInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract CharSequence getApplicationLabel(@NonNull android.content.pm.ApplicationInfo);
     method @Nullable public abstract android.graphics.drawable.Drawable getApplicationLogo(@NonNull android.content.pm.ApplicationInfo);
@@ -12470,10 +12475,10 @@
     method @Nullable public abstract android.graphics.drawable.Drawable getDrawable(@NonNull String, @DrawableRes int, @Nullable android.content.pm.ApplicationInfo);
     method public void getGroupOfPlatformPermission(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.String>);
     method @NonNull public android.content.pm.InstallSourceInfo getInstallSourceInfo(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
+    method @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(int);
     method @NonNull public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplications(@NonNull android.content.pm.PackageManager.ApplicationInfoFlags);
     method @NonNull public java.util.List<android.content.pm.ModuleInfo> getInstalledModules(int);
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
+    method @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackages(int);
     method @NonNull public java.util.List<android.content.pm.PackageInfo> getInstalledPackages(@NonNull android.content.pm.PackageManager.PackageInfoFlags);
     method @Deprecated @Nullable public abstract String getInstallerPackageName(@NonNull String);
     method @NonNull public abstract byte[] getInstantAppCookie();
@@ -12485,20 +12490,20 @@
     method @NonNull public java.util.Set<java.lang.String> getMimeGroup(@NonNull String);
     method @NonNull public android.content.pm.ModuleInfo getModuleInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Nullable public abstract String getNameForUid(int);
-    method @Deprecated @Nullable public android.content.pm.PackageInfo getPackageArchiveInfo(@NonNull String, int);
+    method @Nullable public android.content.pm.PackageInfo getPackageArchiveInfo(@NonNull String, int);
     method @Nullable public android.content.pm.PackageInfo getPackageArchiveInfo(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags);
     method public abstract int[] getPackageGids(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated public abstract int[] getPackageGids(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract int[] getPackageGids(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Nullable public int[] getPackageGids(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated public abstract android.content.pm.PackageInfo getPackageInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.PackageInfo getPackageInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.pm.PackageInfo getPackageInfo(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated public abstract android.content.pm.PackageInfo getPackageInfo(@NonNull android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract android.content.pm.PackageInfo getPackageInfo(@NonNull android.content.pm.VersionedPackage, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.pm.PackageInfo getPackageInfo(@NonNull android.content.pm.VersionedPackage, @NonNull android.content.pm.PackageManager.PackageInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract android.content.pm.PackageInstaller getPackageInstaller();
-    method @Deprecated public abstract int getPackageUid(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method public abstract int getPackageUid(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public int getPackageUid(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Nullable public abstract String[] getPackagesForUid(int);
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(@NonNull String[], int);
+    method @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(@NonNull String[], int);
     method @NonNull public java.util.List<android.content.pm.PackageInfo> getPackagesHoldingPermissions(@NonNull String[], @NonNull android.content.pm.PackageManager.PackageInfoFlags);
     method @NonNull public abstract android.content.pm.PermissionGroupInfo getPermissionGroupInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.pm.PermissionInfo getPermissionInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -12507,17 +12512,17 @@
     method @Deprecated @NonNull public abstract java.util.List<android.content.pm.PackageInfo> getPreferredPackages(int);
     method @NonNull public android.content.pm.PackageManager.Property getProperty(@NonNull String, @NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.pm.PackageManager.Property getProperty(@NonNull String, @NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated @NonNull public abstract android.content.pm.ProviderInfo getProviderInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @NonNull public abstract android.content.pm.ProviderInfo getProviderInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.pm.ProviderInfo getProviderInfo(@NonNull android.content.ComponentName, @NonNull android.content.pm.PackageManager.ComponentInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated @NonNull public abstract android.content.pm.ActivityInfo getReceiverInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @NonNull public abstract android.content.pm.ActivityInfo getReceiverInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.pm.ActivityInfo getReceiverInfo(@NonNull android.content.ComponentName, @NonNull android.content.pm.PackageManager.ComponentInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract android.content.res.Resources getResourcesForActivity(@NonNull android.content.ComponentName) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract android.content.res.Resources getResourcesForApplication(@NonNull android.content.pm.ApplicationInfo) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.res.Resources getResourcesForApplication(@NonNull android.content.pm.ApplicationInfo, @Nullable android.content.res.Configuration) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public abstract android.content.res.Resources getResourcesForApplication(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated @NonNull public abstract android.content.pm.ServiceInfo getServiceInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @NonNull public abstract android.content.pm.ServiceInfo getServiceInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.pm.ServiceInfo getServiceInfo(@NonNull android.content.ComponentName, @NonNull android.content.pm.PackageManager.ComponentInfoFlags) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
+    method @NonNull public abstract java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(int);
     method @NonNull public java.util.List<android.content.pm.SharedLibraryInfo> getSharedLibraries(@NonNull android.content.pm.PackageManager.PackageInfoFlags);
     method @Nullable public android.os.Bundle getSuspendedPackageAppExtras();
     method public boolean getSyntheticAppDetailsActivityEnabled(@NonNull String);
@@ -12546,18 +12551,18 @@
     method public abstract boolean isSafeMode();
     method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryActivityProperty(@NonNull String);
     method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryApplicationProperty(@NonNull String);
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, int);
+    method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, int);
     method @NonNull public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ProviderInfo> queryContentProviders(@Nullable String, int, int);
+    method @NonNull public abstract java.util.List<android.content.pm.ProviderInfo> queryContentProviders(@Nullable String, int, int);
     method @NonNull public java.util.List<android.content.pm.ProviderInfo> queryContentProviders(@Nullable String, int, @NonNull android.content.pm.PackageManager.ComponentInfoFlags);
     method @NonNull public abstract java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(@NonNull String, int);
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(@NonNull android.content.Intent, int);
+    method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(@NonNull android.content.Intent, int);
     method @NonNull public java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(@Nullable android.content.ComponentName, @Nullable android.content.Intent[], @NonNull android.content.Intent, int);
+    method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(@Nullable android.content.ComponentName, @Nullable android.content.Intent[], @NonNull android.content.Intent, int);
     method @NonNull public java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(@Nullable android.content.ComponentName, @Nullable java.util.List<android.content.Intent>, @NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(@NonNull android.content.Intent, int);
+    method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(@NonNull android.content.Intent, int);
     method @NonNull public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(@NonNull android.content.Intent, int);
+    method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(@NonNull android.content.Intent, int);
     method @NonNull public java.util.List<android.content.pm.ResolveInfo> queryIntentServices(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
     method @NonNull public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(@Nullable String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public java.util.List<android.content.pm.PackageManager.Property> queryProviderProperty(@NonNull String);
@@ -12568,11 +12573,11 @@
     method public abstract void removePermission(@NonNull String);
     method @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public boolean removeWhitelistedRestrictedPermission(@NonNull String, @NonNull String, int);
     method public void requestChecksums(@NonNull String, boolean, int, @NonNull java.util.List<java.security.cert.Certificate>, @NonNull android.content.pm.PackageManager.OnChecksumsReadyListener) throws java.security.cert.CertificateEncodingException, android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated @Nullable public abstract android.content.pm.ResolveInfo resolveActivity(@NonNull android.content.Intent, int);
+    method @Nullable public abstract android.content.pm.ResolveInfo resolveActivity(@NonNull android.content.Intent, int);
     method @Nullable public android.content.pm.ResolveInfo resolveActivity(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
-    method @Deprecated @Nullable public abstract android.content.pm.ProviderInfo resolveContentProvider(@NonNull String, int);
+    method @Nullable public abstract android.content.pm.ProviderInfo resolveContentProvider(@NonNull String, int);
     method @Nullable public android.content.pm.ProviderInfo resolveContentProvider(@NonNull String, @NonNull android.content.pm.PackageManager.ComponentInfoFlags);
-    method @Deprecated @Nullable public abstract android.content.pm.ResolveInfo resolveService(@NonNull android.content.Intent, int);
+    method @Nullable public abstract android.content.pm.ResolveInfo resolveService(@NonNull android.content.Intent, int);
     method @Nullable public android.content.pm.ResolveInfo resolveService(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags);
     method public abstract void setApplicationCategoryHint(@NonNull String, int);
     method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public abstract void setApplicationEnabledSetting(@NonNull String, int, int);
@@ -19529,9 +19534,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 @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig);
+    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig, @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);
@@ -19586,6 +19591,30 @@
     method public void onStopped();
   }
 
+  public final class VirtualDisplayConfig implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getDensityDpi();
+    method @NonNull public java.util.List<java.lang.String> getDisplayCategories();
+    method public int getFlags();
+    method public int getHeight();
+    method @NonNull public String getName();
+    method public float getRequestedRefreshRate();
+    method @Nullable public android.view.Surface getSurface();
+    method public int getWidth();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.VirtualDisplayConfig> CREATOR;
+  }
+
+  public static final class VirtualDisplayConfig.Builder {
+    ctor public VirtualDisplayConfig.Builder(@NonNull String, @IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int);
+    method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder addDisplayCategory(@NonNull String);
+    method @NonNull public android.hardware.display.VirtualDisplayConfig build();
+    method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setDisplayCategories(@NonNull java.util.List<java.lang.String>);
+    method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setFlags(int);
+    method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setRequestedRefreshRate(@FloatRange(from=0.0f) float);
+    method @NonNull public android.hardware.display.VirtualDisplayConfig.Builder setSurface(@Nullable android.view.Surface);
+  }
+
 }
 
 package android.hardware.fingerprint {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 47d9ab6..035e8b4 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -588,6 +588,7 @@
     method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(@NonNull String, int, @Nullable String, int);
     method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(@NonNull String, int, int);
     method @RequiresPermission(value="android.permission.WATCH_APPOPS", conditional=true) public void startWatchingNoted(@NonNull String[], @NonNull android.app.AppOpsManager.OnOpNotedListener);
+    method @RequiresPermission(value="android.permission.WATCH_APPOPS", conditional=true) public void startWatchingNoted(@NonNull String[], @NonNull java.util.concurrent.Executor, @NonNull android.app.AppOpsManager.OnOpNotedListener);
     method public void stopWatchingNoted(@NonNull android.app.AppOpsManager.OnOpNotedListener);
     field public static final int HISTORY_FLAGS_ALL = 3; // 0x3
     field public static final int HISTORY_FLAG_AGGREGATE = 1; // 0x1
@@ -1698,7 +1699,7 @@
     method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupEnabled();
     method @RequiresPermission(android.Manifest.permission.BACKUP) public boolean isBackupServiceActive(android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public String[] listAllTransports();
-    method @NonNull public void reportDelayedRestoreResult(@NonNull android.app.backup.BackupRestoreEventLogger);
+    method public void reportDelayedRestoreResult(@NonNull android.app.backup.BackupRestoreEventLogger);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public int requestBackup(String[], android.app.backup.BackupObserver);
     method @RequiresPermission(android.Manifest.permission.BACKUP) public int requestBackup(String[], android.app.backup.BackupObserver, android.app.backup.BackupManagerMonitor, int);
     method @Deprecated public int requestRestore(android.app.backup.RestoreObserver, android.app.backup.BackupManagerMonitor);
@@ -3216,8 +3217,8 @@
     method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close();
     method @NonNull public android.content.Context createContext();
     method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.audio.VirtualAudioDevice createVirtualAudioDevice(@NonNull android.hardware.display.VirtualDisplay, @Nullable java.util.concurrent.Executor, @Nullable android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback);
-    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
-    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @NonNull java.util.List<java.lang.String>, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
+    method @Deprecated @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
+    method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull android.hardware.display.VirtualDisplayConfig, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
     method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualDpad createVirtualDpad(@NonNull android.hardware.input.VirtualDpadConfig);
     method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.input.VirtualKeyboardConfig);
     method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
@@ -3346,10 +3347,15 @@
 
   public interface VirtualSensorCallback {
     method public void onConfigurationChanged(@NonNull android.companion.virtual.sensor.VirtualSensor, boolean, @NonNull java.time.Duration, @NonNull java.time.Duration);
+    method public default void onDirectChannelConfigured(@IntRange(from=1) int, @NonNull android.companion.virtual.sensor.VirtualSensor, int, @IntRange(from=1) int);
+    method public default void onDirectChannelCreated(@IntRange(from=1) int, @NonNull android.os.SharedMemory);
+    method public default void onDirectChannelDestroyed(@IntRange(from=1) int);
   }
 
   public final class VirtualSensorConfig implements android.os.Parcelable {
     method public int describeContents();
+    method public int getDirectChannelTypesSupported();
+    method public int getHighestDirectReportRateLevel();
     method @NonNull public String getName();
     method public int getType();
     method @Nullable public String getVendor();
@@ -3360,6 +3366,8 @@
   public static final class VirtualSensorConfig.Builder {
     ctor public VirtualSensorConfig.Builder(int, @NonNull String);
     method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig build();
+    method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setDirectChannelTypesSupported(int);
+    method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setHighestDirectReportRateLevel(int);
     method @NonNull public android.companion.virtual.sensor.VirtualSensorConfig.Builder setVendor(@Nullable String);
   }
 
@@ -3864,15 +3872,15 @@
     method @NonNull public boolean canUserUninstall(@NonNull String, @NonNull android.os.UserHandle);
     method @NonNull public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(@NonNull String);
     method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_METADATA) public android.os.PersistableBundle getAppMetadata(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
+    method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, @NonNull android.content.pm.PackageManager.ApplicationInfoFlags, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
     method @NonNull public android.content.pm.dex.ArtManager getArtManager();
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_SHARED_LIBRARIES) public java.util.List<android.content.pm.SharedLibraryInfo> getDeclaredSharedLibraries(@NonNull String, int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_SHARED_LIBRARIES) public java.util.List<android.content.pm.SharedLibraryInfo> getDeclaredSharedLibraries(@NonNull String, int);
     method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_SHARED_LIBRARIES) public java.util.List<android.content.pm.SharedLibraryInfo> getDeclaredSharedLibraries(@NonNull String, @NonNull android.content.pm.PackageManager.PackageInfoFlags);
     method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract String getDefaultBrowserPackageNameAsUser(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.SET_HARMFUL_APP_WARNINGS) public CharSequence getHarmfulAppWarning(@NonNull String);
     method @Nullable public String getIncidentReportApproverPackageName();
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
+    method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(int, int);
     method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public java.util.List<android.content.pm.PackageInfo> getInstalledPackagesAsUser(@NonNull android.content.pm.PackageManager.PackageInfoFlags, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_INSTANT_APPS) public abstract android.graphics.drawable.Drawable getInstantAppIcon(String);
     method @Nullable public abstract android.content.ComponentName getInstantAppInstallerComponent();
@@ -3886,13 +3894,13 @@
     method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method @Deprecated public abstract int installExistingPackage(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Deprecated public abstract int installExistingPackage(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(@NonNull android.content.Intent, int, android.os.UserHandle);
+    method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(@NonNull android.content.Intent, int, android.os.UserHandle);
     method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags, @NonNull android.os.UserHandle);
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentActivitiesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
+    method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentActivitiesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
     method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentActivitiesAsUser(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags, @NonNull android.os.UserHandle);
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProvidersAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
+    method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProvidersAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
     method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProvidersAsUser(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags, @NonNull android.os.UserHandle);
-    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentServicesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
+    method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentServicesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
     method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentServicesAsUser(@NonNull android.content.Intent, @NonNull android.content.pm.PackageManager.ResolveInfoFlags, @NonNull android.os.UserHandle);
     method public abstract void registerDexModule(@NonNull String, @Nullable android.content.pm.PackageManager.DexModuleRegisterCallback);
     method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void removeOnPermissionsChangeListener(@NonNull android.content.pm.PackageManager.OnPermissionsChangedListener);
@@ -9993,49 +10001,81 @@
 
 package android.net.wifi.sharedconnectivity.app {
 
-  public final class DeviceInfo implements android.os.Parcelable {
+  public final class HotspotNetwork implements android.os.Parcelable {
     method public int describeContents();
-    method @IntRange(from=0, to=100) public int getBatteryPercentage();
-    method @IntRange(from=0, to=3) public int getConnectionStrength();
-    method @NonNull public String getDeviceName();
-    method public int getDeviceType();
-    method @NonNull public String getModelName();
+    method public long getDeviceId();
+    method public int getHostNetworkType();
+    method @Nullable public String getHotspotBssid();
+    method @NonNull public java.util.Set<java.lang.Integer> getHotspotSecurityTypes();
+    method @Nullable public String getHotspotSsid();
+    method @NonNull public String getNetworkName();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo getNetworkProviderInfo();
     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
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.HotspotNetwork> 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 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 static final class HotspotNetwork.Builder {
+    ctor public HotspotNetwork.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder addHotspotSecurityType(int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setDeviceId(long);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHostNetworkType(int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHotspotBssid(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setHotspotSsid(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setNetworkName(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork.Builder setNetworkProviderInfo(@NonNull android.net.wifi.sharedconnectivity.app.NetworkProviderInfo);
+  }
+
+  public final class HotspotNetworkConnectionStatus implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.os.Bundle getExtras();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetwork getHotspotNetwork();
+    method public int getStatus();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9; // 0x9
+    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1; // 0x1
+    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7; // 0x7
+    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8; // 0x8
+    field public static final int CONNECTION_STATUS_NO_CELL_DATA = 6; // 0x6
+    field public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3; // 0x3
+    field public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4; // 0x4
+    field public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5; // 0x5
+    field public static final int CONNECTION_STATUS_UNKNOWN = 0; // 0x0
+    field public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2; // 0x2
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus> CREATOR;
+  }
+
+  public static final class HotspotNetworkConnectionStatus.Builder {
+    ctor public HotspotNetworkConnectionStatus.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setExtras(@NonNull android.os.Bundle);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.Builder setStatus(int);
   }
 
   public final class KnownNetwork implements android.os.Parcelable {
     method public int describeContents();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.DeviceInfo getDeviceInfo();
+    method @Nullable public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo getNetworkProviderInfo();
     method public int getNetworkSource();
-    method @NonNull public int[] getSecurityTypes();
+    method @NonNull public java.util.Set<java.lang.Integer> 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
+    field public static final int NETWORK_SOURCE_CLOUD_SELF = 2; // 0x2
+    field public static final int NETWORK_SOURCE_NEARBY_SELF = 1; // 0x1
+    field public static final int NETWORK_SOURCE_UNKNOWN = 0; // 0x0
   }
 
   public static final class KnownNetwork.Builder {
     ctor public KnownNetwork.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetwork.Builder addSecurityType(int);
     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 setNetworkProviderInfo(@Nullable android.net.wifi.sharedconnectivity.app.NetworkProviderInfo);
     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);
   }
 
@@ -10059,24 +10099,56 @@
     method @NonNull public android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.Builder setStatus(int);
   }
 
+  public final class NetworkProviderInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @IntRange(from=0, to=100) public int getBatteryPercentage();
+    method @IntRange(from=0, to=3) 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.NetworkProviderInfo> CREATOR;
+    field public static final int DEVICE_TYPE_AUTO = 5; // 0x5
+    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
+    field public static final int DEVICE_TYPE_WATCH = 4; // 0x4
+  }
+
+  public static final class NetworkProviderInfo.Builder {
+    ctor public NetworkProviderInfo.Builder();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo build();
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setBatteryPercentage(@IntRange(from=0, to=100) int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setConnectionStrength(@IntRange(from=0, to=3) int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceName(@NonNull String);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setDeviceType(int);
+    method @NonNull public android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder setModelName(@NonNull String);
+  }
+
   public interface SharedConnectivityClientCallback {
+    method public void onHotspotNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus);
+    method public void onHotspotNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork>);
     method public void onKnownNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus);
     method public void onKnownNetworksUpdated(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork>);
     method public void onRegisterCallbackFailed(@NonNull Exception);
     method public void onServiceConnected();
     method public void onServiceDisconnected();
     method public void onSharedConnectivitySettingsChanged(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState);
-    method public void onTetherNetworkConnectionStatusChanged(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus);
-    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(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
-    method public boolean forgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
-    method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
-    method public boolean unregisterCallback(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean connectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean connectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean disconnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean forgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus();
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork> getHotspotNetworks();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus getKnownNetworkConnectionStatus();
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.sharedconnectivity.app.KnownNetwork> getKnownNetworks();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState getSettingsState();
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public boolean unregisterCallback(@NonNull android.net.wifi.sharedconnectivity.app.SharedConnectivityClientCallback);
   }
 
   public final class SharedConnectivitySettingsState implements android.os.Parcelable {
@@ -10094,62 +10166,6 @@
     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 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 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);
-  }
-
-  public final class TetherNetworkConnectionStatus implements android.os.Parcelable {
-    method public int describeContents();
-    method @NonNull public android.os.Bundle getExtras();
-    method public int getStatus();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetwork getTetherNetwork();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field public static final int CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED = 9; // 0x9
-    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1; // 0x1
-    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_FAILED = 7; // 0x7
-    field public static final int CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT = 8; // 0x8
-    field public static final int CONNECTION_STATUS_NO_CELL_DATA = 6; // 0x6
-    field public static final int CONNECTION_STATUS_PROVISIONING_FAILED = 3; // 0x3
-    field public static final int CONNECTION_STATUS_TETHERING_TIMEOUT = 4; // 0x4
-    field public static final int CONNECTION_STATUS_TETHERING_UNSUPPORTED = 5; // 0x5
-    field public static final int CONNECTION_STATUS_UNKNOWN = 0; // 0x0
-    field public static final int CONNECTION_STATUS_UNKNOWN_ERROR = 2; // 0x2
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus> CREATOR;
-  }
-
-  public static final class TetherNetworkConnectionStatus.Builder {
-    ctor public TetherNetworkConnectionStatus.Builder();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus build();
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setExtras(@NonNull android.os.Bundle);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setStatus(int);
-    method @NonNull public android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.Builder setTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
-  }
-
 }
 
 package android.net.wifi.sharedconnectivity.service {
@@ -10157,15 +10173,15 @@
   public abstract class SharedConnectivityService extends android.app.Service {
     ctor public SharedConnectivityService();
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method public abstract void onConnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
     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(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
+    method public abstract void onDisconnectHotspotNetwork(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetwork);
     method public abstract void onForgetKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
+    method public final void setHotspotNetworks(@NonNull java.util.List<android.net.wifi.sharedconnectivity.app.HotspotNetwork>);
     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>);
+    method public final void updateHotspotNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus);
     method public final void updateKnownNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus);
-    method public final void updateTetherNetworkConnectionStatus(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus);
   }
 
 }
@@ -13249,22 +13265,18 @@
 
   public abstract class VisualQueryDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionServiceBase {
     ctor public VisualQueryDetectionService();
+    method public final void finishQuery() throws java.lang.IllegalStateException;
+    method public final void gainedAttention();
+    method public final void lostAttention();
     method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
-    method public void onStartDetection(@NonNull android.service.voice.VisualQueryDetectionService.Callback);
+    method public void onStartDetection();
     method public void onStopDetection();
     method public void onUpdateState(@Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, long, @Nullable java.util.function.IntConsumer);
+    method public final void rejectQuery() throws java.lang.IllegalStateException;
+    method public final void streamQuery(@NonNull String) throws java.lang.IllegalStateException;
     field public static final String SERVICE_INTERFACE = "android.service.voice.VisualQueryDetectionService";
   }
 
-  public static final class VisualQueryDetectionService.Callback {
-    ctor public VisualQueryDetectionService.Callback();
-    method public void onAttentionGained();
-    method public void onAttentionLost();
-    method public void onQueryDetected(@NonNull String) throws java.lang.IllegalStateException;
-    method public void onQueryFinished() throws java.lang.IllegalStateException;
-    method public void onQueryRejected() throws java.lang.IllegalStateException;
-  }
-
   public final class VisualQueryDetectionServiceFailure extends android.service.voice.DetectorFailure {
     method public int getErrorCode();
     method public int getSuggestedAction();
@@ -17277,9 +17289,9 @@
   public final class AccessibilityManager {
     method public int getAccessibilityWindowId(@Nullable android.os.IBinder);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void performAccessibilityShortcut();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public boolean registerDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
+    method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_ACCESSIBILITY, android.Manifest.permission.CREATE_VIRTUAL_DEVICE}) public boolean registerDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void registerSystemAction(@NonNull android.app.RemoteAction, int);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public boolean unregisterDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
+    method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_ACCESSIBILITY, android.Manifest.permission.CREATE_VIRTUAL_DEVICE}) public boolean unregisterDisplayProxy(@NonNull android.view.accessibility.AccessibilityDisplayProxy);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void unregisterSystemAction(int);
   }
 
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 640506d..43fa6e2 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -145,7 +145,8 @@
     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_IMPLICIT = 6; // 0x6
-    field public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
+    field @Deprecated public static final int PROCESS_CAPABILITY_NETWORK = 8; // 0x8
+    field public static final int PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK = 8; // 0x8
     field public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4; // 0x4
     field public static final int PROCESS_STATE_TOP = 2; // 0x2
     field public static final int STOP_USER_ON_SWITCH_DEFAULT = -1; // 0xffffffff
@@ -930,7 +931,7 @@
     method @Nullable public String getDefaultTextClassifierPackageName();
     method @RequiresPermission(android.Manifest.permission.INJECT_EVENTS) public android.os.IBinder getHoldLockToken();
     method public abstract int getInstallReason(@NonNull String, @NonNull android.os.UserHandle);
-    method @Deprecated @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
+    method @NonNull public abstract java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(int, int);
     method @NonNull public java.util.List<android.content.pm.ApplicationInfo> getInstalledApplicationsAsUser(@NonNull android.content.pm.PackageManager.ApplicationInfoFlags, int);
     method @Nullable public abstract String[] getNamesForUids(int[]);
     method @NonNull public String getPermissionControllerPackageName();
@@ -2180,6 +2181,7 @@
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createRestrictedProfile(@Nullable String);
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.content.pm.UserInfo createUser(@Nullable String, @NonNull String, int);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle getBootUser();
+    method public int getDisplayIdAssignedToUser();
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public java.util.Set<java.lang.String> getPreInstallableSystemPackages(@NonNull String);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS, android.Manifest.permission.QUERY_USERS}) public String getUserType();
     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);
@@ -3546,6 +3548,8 @@
   public final class InputMethodInfo implements android.os.Parcelable {
     ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, boolean, @NonNull String);
     ctor public InputMethodInfo(@NonNull String, @NonNull String, @NonNull CharSequence, @NonNull String, int);
+    field public static final int COMPONENT_NAME_MAX_LENGTH = 1000; // 0x3e8
+    field public static final int MAX_IMES_PER_PACKAGE = 20; // 0x14
   }
 
   public final class InputMethodManager {
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 6422865..3615435 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -198,6 +198,26 @@
  * possible for a node to contain outdated information because the window content may change at any
  * time.
  * </p>
+ * <h3>Drawing Accessibility Overlays</h3>
+ * <p>Accessibility services can draw overlays on top of existing screen contents.
+ * Accessibility overlays can be used to visually highlight items on the screen
+ * e.g. indicate the current item with accessibility focus.
+ * Overlays can also offer the user a way to interact with the service directly and quickly
+ * customize the service's behavior.</p>
+ * <p>Accessibility overlays can be attached to a particular window or to the display itself.
+ * Attaching an overlay to a window allows the overly to move, grow and shrink as the window does.
+ * The overlay will maintain the same relative position within the window bounds as the window
+ * moves. The overlay will also maintain the same relative position within the window bounds if
+ * the window is resized.
+ * To attach an overlay to a window, use {@link attachAccessibilityOverlayToWindow}.
+ * Attaching an overlay to the display means that the overlay is independent of the active
+ * windows on that display.
+ * To attach an overlay to a display, use {@link attachAccessibilityOverlayToDisplay}. </p>
+ * <p> When positioning an overlay that is attached to a window, the service must use window
+ * coordinates. In order to position an overlay on top of an existing UI element it is necessary
+ * to know the bounds of that element in window coordinates. To find the bounds in window
+ * coordinates of an element, find the corresponding {@link AccessibilityNodeInfo} as discussed
+ * above and call {@link AccessibilityNodeInfo#getBoundsInWindow}. </p>
  * <h3>Notification strategy</h3>
  * <p>
  * All accessibility services are notified of all events they have requested, regardless of their
@@ -3421,22 +3441,28 @@
     }
 
     /**
-     * Attaches a {@link android.view.SurfaceControl} containing an accessibility
+     * <p>Attaches a {@link android.view.SurfaceControl} containing an accessibility
      * overlay to the
      * specified display. This type of overlay should be used for content that does
      * not need to
      * track the location and size of Views in the currently active app e.g. service
      * configuration
-     * or general service UI. To remove this overlay and free the associated
+     * or general service UI.</p>
+     * <p>Generally speaking, an accessibility overlay  will be  a {@link android.view.View}.
+     * To embed the View into a {@link android.view.SurfaceControl}, create a
+     * {@link android.view.SurfaceControlViewHost} and attach the View using
+     * {@link android.view.SurfaceControlViewHost#setView}. Then obtain the SurfaceControl by
+     * calling <code> viewHost.getSurfacePackage().getSurfaceControl()</code>.</p>
+     * <p>To remove this overlay and free the associated
      * resources, use
-     * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
-     * If the specified overlay has already been attached to the specified display
+     * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.</p>
+     * <p>If the specified overlay has already been attached to the specified display
      * this method does nothing.
      * If the specified overlay has already been attached to a previous display this
      * function will transfer the overlay to the new display.
      * Services can attach multiple overlays. Use
      * <code> new SurfaceControl.Transaction().setLayer(sc, layer).apply();</code>.
-     * to coordinate the order of the overlays on screen.
+     * to coordinate the order of the overlays on screen.</p>
      *
      * @param displayId the display to which the SurfaceControl should be attached.
      * @param sc        the SurfaceControl containing the overlay content
@@ -3456,20 +3482,24 @@
     }
 
     /**
-     * Attaches an accessibility overlay {@link android.view.SurfaceControl} to the
+     * <p>Attaches an accessibility overlay {@link android.view.SurfaceControl} to the
      * specified
      * window. This method should be used when you want the overlay to move and
-     * resize as the parent
-     * window moves and resizes. To remove this overlay and free the associated
-     * resources, use
-     * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.
-     * If the specified overlay has already been attached to the specified window
+     * resize as the parent window moves and resizes.</p>
+     * <p>Generally speaking, an accessibility overlay  will be  a {@link android.view.View}.
+     * To embed the View into a {@link android.view.SurfaceControl}, create a
+     * {@link android.view.SurfaceControlViewHost} and attach the View using
+     * {@link android.view.SurfaceControlViewHost#setView}. Then obtain the SurfaceControl by
+     * calling <code> viewHost.getSurfacePackage().getSurfaceControl()</code>.</p>
+     * <p>To remove this overlay and free the associated resources, use
+     * <code> new SurfaceControl.Transaction().reparent(sc, null).apply();</code>.</p>
+     * <p>If the specified overlay has already been attached to the specified window
      * this method does nothing.
      * If the specified overlay has already been attached to a previous window this
      * function will transfer the overlay to the new window.
      * Services can attach multiple overlays. Use
      * <code> new SurfaceControl.Transaction().setLayer(sc, layer).apply();</code>.
-     * to coordinate the order of the overlays on screen.
+     * to coordinate the order of the overlays on screen.</p>
      *
      * @param accessibilityWindowId The window id, from
      *                              {@link AccessibilityWindowInfo#getId()}.
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 8b6d7cb..ba36d93 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -751,9 +751,17 @@
     @SystemApi
     public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2;
 
-    /** @hide Process can access network despite any power saving resrictions */
+    /** @hide Process can access network despite any power saving restrictions */
     @TestApi
-    public static final int PROCESS_CAPABILITY_NETWORK = 1 << 3;
+    public static final int PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK = 1 << 3;
+    /**
+     * @hide
+     * @deprecated Use {@link #PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK} instead.
+     */
+    @TestApi
+    @Deprecated
+    public static final int PROCESS_CAPABILITY_NETWORK =
+            PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK;
 
     /**
      * Flag used to indicate whether an app is allowed to start a foreground service from the
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index b9f38d3..d810f05 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -968,14 +968,6 @@
     public abstract void stopForegroundServiceDelegate(@NonNull ServiceConnection connection);
 
     /**
-     * Called by PowerManager. Return whether a given procstate is allowed to hold
-     * wake locks in deep doze. Because it's called with the power manager lock held, we can't
-     * hold AM locks in it.
-     * @hide
-     */
-    public abstract boolean canHoldWakeLocksInDeepDoze(int uid, int procstate);
-
-    /**
      * Same as {@link android.app.IActivityManager#startProfile(int userId)}, but it would succeed
      * even if the profile is disabled - it should only be called by
      * {@link com.android.server.devicepolicy.DevicePolicyManagerService} when starting a profile
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b50245d..dfdfd0e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -36,6 +36,7 @@
 import static android.window.ConfigurationHelper.shouldUpdateResources;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+import static com.android.internal.os.SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -49,6 +50,7 @@
 import android.app.backup.BackupAgent;
 import android.app.backup.BackupAnnotations.BackupDestination;
 import android.app.backup.BackupAnnotations.OperationType;
+import android.app.compat.CompatChanges;
 import android.app.servertransaction.ActivityLifecycleItem;
 import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
 import android.app.servertransaction.ActivityRelaunchItem;
@@ -206,6 +208,7 @@
 import com.android.internal.os.BinderCallsStats;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.RuntimeInit;
+import com.android.internal.os.SafeZipPathValidatorCallback;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.policy.DecorView;
 import com.android.internal.util.ArrayUtils;
@@ -219,6 +222,7 @@
 import dalvik.system.CloseGuard;
 import dalvik.system.VMDebug;
 import dalvik.system.VMRuntime;
+import dalvik.system.ZipPathValidator;
 
 import libcore.io.ForwardingOs;
 import libcore.io.IoUtils;
@@ -554,9 +558,6 @@
         boolean hideForNow;
         Configuration createdConfig;
         Configuration overrideConfig;
-        // TODO(b/263402465): pass deviceId directly in LaunchActivityItem#execute
-        // The deviceId assigned by the server when this activity was first started.
-        int mDeviceId;
         // Used for consolidating configs before sending on to Activity.
         private Configuration tmpConfig = new Configuration();
         // Callback used for updating activity override config and camera compat control state.
@@ -619,7 +620,7 @@
         }
 
         public ActivityClientRecord(IBinder token, Intent intent, int ident,
-                ActivityInfo info, Configuration overrideConfig, int deviceId,
+                ActivityInfo info, Configuration overrideConfig,
                 String referrer, IVoiceInteractor voiceInteractor, Bundle state,
                 PersistableBundle persistentState, List<ResultInfo> pendingResults,
                 List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
@@ -641,7 +642,6 @@
             this.isForward = isForward;
             this.profilerInfo = profilerInfo;
             this.overrideConfig = overrideConfig;
-            this.mDeviceId = deviceId;
             this.packageInfo = client.getPackageInfoNoCheck(activityInfo.applicationInfo);
             mActivityOptions = activityOptions;
             mLaunchedFromBubble = launchedFromBubble;
@@ -3872,7 +3872,7 @@
      */
     @Override
     public Activity handleLaunchActivity(ActivityClientRecord r,
-            PendingTransactionActions pendingActions, Intent customIntent) {
+            PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
         // If we are getting ready to gc after going to the background, well
         // we are back active so skip it.
         unscheduleGcIdler();
@@ -3885,7 +3885,7 @@
 
         // Make sure we are running with the most recent config.
         mConfigurationController.handleConfigurationChanged(null, null);
-        updateDeviceIdForNonUIContexts(r.mDeviceId);
+        updateDeviceIdForNonUIContexts(deviceId);
 
         if (localLOGV) Slog.v(
             TAG, "Handling launch of " + r);
@@ -4621,7 +4621,7 @@
                     ActivityManager.getService());
             if (!service.isUiContext()) { // WindowProviderService is a UI Context.
                 VirtualDeviceManager vdm = context.getSystemService(VirtualDeviceManager.class);
-                if (mLastReportedDeviceId == VirtualDeviceManager.DEVICE_ID_DEFAULT
+                if (mLastReportedDeviceId == Context.DEVICE_ID_DEFAULT
                         || vdm.isValidVirtualDeviceId(mLastReportedDeviceId)) {
                     service.updateDeviceId(mLastReportedDeviceId);
                 }
@@ -5942,7 +5942,7 @@
         r.startsNotResumed = startsNotResumed;
         r.overrideConfig = overrideConfig;
 
-        handleLaunchActivity(r, pendingActions, customIntent);
+        handleLaunchActivity(r, pendingActions, mLastReportedDeviceId, customIntent);
     }
 
     @Override
@@ -6149,7 +6149,7 @@
 
     private void updateDeviceIdForNonUIContexts(int deviceId) {
         // Invalid device id is treated as a no-op.
-        if (deviceId == VirtualDeviceManager.DEVICE_ID_INVALID) {
+        if (deviceId == Context.DEVICE_ID_INVALID) {
             return;
         }
         if (deviceId == mLastReportedDeviceId) {
@@ -6703,6 +6703,11 @@
         // Let libcore handle any compat changes after installing the list of compat changes.
         AppSpecializationHooks.handleCompatChangesBeforeBindingApplication();
 
+        // Initialize the zip path validator callback depending on the targetSdk.
+        // This has to be after AppCompatCallbacks#install() so that the Compat
+        // checks work accordingly.
+        initZipPathValidatorCallback();
+
         mBoundApplication = data;
         mConfigurationController.setConfiguration(data.config);
         mConfigurationController.setCompatConfiguration(data.config);
@@ -7070,6 +7075,18 @@
         }
     }
 
+    /**
+     * If targetSDK >= U: set the safe zip path validator callback which disallows dangerous zip
+     * entry names.
+     * Otherwise: clear the callback to the default validation.
+     */
+    private void initZipPathValidatorCallback() {
+        if (CompatChanges.isChangeEnabled(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL)) {
+            ZipPathValidator.setCallback(new SafeZipPathValidatorCallback());
+        } else {
+            ZipPathValidator.clearCallback();
+        }
+    }
 
     private void handleSetContentCaptureOptionsCallback(String packageName) {
         if (mContentCaptureOptionsCallback != null) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 40ed269..9bf9e0c 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -25,6 +25,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.StringDef;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -1464,6 +1465,149 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public static final int _NUM_OP = 134;
 
+    /**
+     * All app ops represented as strings.
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @StringDef(prefix = { "OPSTR_" }, value = {
+            OPSTR_COARSE_LOCATION,
+            OPSTR_FINE_LOCATION,
+            OPSTR_MONITOR_LOCATION,
+            OPSTR_MONITOR_HIGH_POWER_LOCATION,
+            OPSTR_GET_USAGE_STATS,
+            OPSTR_ACTIVATE_VPN,
+            OPSTR_READ_CONTACTS,
+            OPSTR_WRITE_CONTACTS,
+            OPSTR_READ_CALL_LOG,
+            OPSTR_WRITE_CALL_LOG,
+            OPSTR_READ_CALENDAR,
+            OPSTR_WRITE_CALENDAR,
+            OPSTR_CALL_PHONE,
+            OPSTR_READ_SMS,
+            OPSTR_RECEIVE_SMS,
+            OPSTR_RECEIVE_MMS,
+            OPSTR_RECEIVE_WAP_PUSH,
+            OPSTR_SEND_SMS,
+            OPSTR_CAMERA,
+            OPSTR_RECORD_AUDIO,
+            OPSTR_READ_PHONE_STATE,
+            OPSTR_ADD_VOICEMAIL,
+            OPSTR_USE_SIP,
+            OPSTR_PROCESS_OUTGOING_CALLS,
+            OPSTR_USE_FINGERPRINT,
+            OPSTR_BODY_SENSORS,
+            OPSTR_READ_CELL_BROADCASTS,
+            OPSTR_MOCK_LOCATION,
+            OPSTR_READ_EXTERNAL_STORAGE,
+            OPSTR_WRITE_EXTERNAL_STORAGE,
+            OPSTR_SYSTEM_ALERT_WINDOW,
+            OPSTR_WRITE_SETTINGS,
+            OPSTR_GET_ACCOUNTS,
+            OPSTR_READ_PHONE_NUMBERS,
+            OPSTR_PICTURE_IN_PICTURE,
+            OPSTR_INSTANT_APP_START_FOREGROUND,
+            OPSTR_ANSWER_PHONE_CALLS,
+            OPSTR_ACCEPT_HANDOVER,
+            OPSTR_GPS,
+            OPSTR_VIBRATE,
+            OPSTR_WIFI_SCAN,
+            OPSTR_POST_NOTIFICATION,
+            OPSTR_NEIGHBORING_CELLS,
+            OPSTR_WRITE_SMS,
+            OPSTR_RECEIVE_EMERGENCY_BROADCAST,
+            OPSTR_READ_ICC_SMS,
+            OPSTR_WRITE_ICC_SMS,
+            OPSTR_ACCESS_NOTIFICATIONS,
+            OPSTR_PLAY_AUDIO,
+            OPSTR_READ_CLIPBOARD,
+            OPSTR_WRITE_CLIPBOARD,
+            OPSTR_TAKE_MEDIA_BUTTONS,
+            OPSTR_TAKE_AUDIO_FOCUS,
+            OPSTR_AUDIO_MASTER_VOLUME,
+            OPSTR_AUDIO_VOICE_VOLUME,
+            OPSTR_AUDIO_RING_VOLUME,
+            OPSTR_AUDIO_MEDIA_VOLUME,
+            OPSTR_AUDIO_ALARM_VOLUME,
+            OPSTR_AUDIO_NOTIFICATION_VOLUME,
+            OPSTR_AUDIO_BLUETOOTH_VOLUME,
+            OPSTR_WAKE_LOCK,
+            OPSTR_MUTE_MICROPHONE,
+            OPSTR_TOAST_WINDOW,
+            OPSTR_PROJECT_MEDIA,
+            OPSTR_WRITE_WALLPAPER,
+            OPSTR_ASSIST_STRUCTURE,
+            OPSTR_ASSIST_SCREENSHOT,
+            OPSTR_TURN_SCREEN_ON,
+            OPSTR_RUN_IN_BACKGROUND,
+            OPSTR_AUDIO_ACCESSIBILITY_VOLUME,
+            OPSTR_REQUEST_INSTALL_PACKAGES,
+            OPSTR_RUN_ANY_IN_BACKGROUND,
+            OPSTR_CHANGE_WIFI_STATE,
+            OPSTR_REQUEST_DELETE_PACKAGES,
+            OPSTR_BIND_ACCESSIBILITY_SERVICE,
+            OPSTR_MANAGE_IPSEC_TUNNELS,
+            OPSTR_START_FOREGROUND,
+            OPSTR_BLUETOOTH_SCAN,
+            OPSTR_BLUETOOTH_CONNECT,
+            OPSTR_BLUETOOTH_ADVERTISE,
+            OPSTR_USE_BIOMETRIC,
+            OPSTR_ACTIVITY_RECOGNITION,
+            OPSTR_SMS_FINANCIAL_TRANSACTIONS,
+            OPSTR_READ_MEDIA_AUDIO,
+            OPSTR_WRITE_MEDIA_AUDIO,
+            OPSTR_READ_MEDIA_VIDEO,
+            OPSTR_WRITE_MEDIA_VIDEO,
+            OPSTR_READ_MEDIA_IMAGES,
+            OPSTR_WRITE_MEDIA_IMAGES,
+            OPSTR_LEGACY_STORAGE,
+            OPSTR_ACCESS_MEDIA_LOCATION,
+            OPSTR_ACCESS_ACCESSIBILITY,
+            OPSTR_READ_DEVICE_IDENTIFIERS,
+            OPSTR_QUERY_ALL_PACKAGES,
+            OPSTR_MANAGE_EXTERNAL_STORAGE,
+            OPSTR_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
+            OPSTR_AUTO_REVOKE_MANAGED_BY_INSTALLER,
+            OPSTR_INTERACT_ACROSS_PROFILES,
+            OPSTR_ACTIVATE_PLATFORM_VPN,
+            OPSTR_LOADER_USAGE_STATS,
+            OPSTR_MANAGE_ONGOING_CALLS,
+            OPSTR_NO_ISOLATED_STORAGE,
+            OPSTR_PHONE_CALL_MICROPHONE,
+            OPSTR_PHONE_CALL_CAMERA,
+            OPSTR_RECORD_AUDIO_HOTWORD,
+            OPSTR_MANAGE_CREDENTIALS,
+            OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+            OPSTR_RECORD_AUDIO_OUTPUT,
+            OPSTR_SCHEDULE_EXACT_ALARM,
+            OPSTR_FINE_LOCATION_SOURCE,
+            OPSTR_COARSE_LOCATION_SOURCE,
+            OPSTR_MANAGE_MEDIA,
+            OPSTR_UWB_RANGING,
+            OPSTR_NEARBY_WIFI_DEVICES,
+            OPSTR_ACTIVITY_RECOGNITION_SOURCE,
+            OPSTR_RECORD_INCOMING_PHONE_AUDIO,
+            OPSTR_ESTABLISH_VPN_SERVICE,
+            OPSTR_ESTABLISH_VPN_MANAGER,
+            OPSTR_ACCESS_RESTRICTED_SETTINGS,
+            OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
+            OPSTR_READ_MEDIA_VISUAL_USER_SELECTED,
+            OPSTR_READ_WRITE_HEALTH_DATA,
+            OPSTR_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO,
+            OPSTR_RUN_USER_INITIATED_JOBS,
+            OPSTR_SYSTEM_EXEMPT_FROM_SUSPENSION,
+            OPSTR_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS,
+            OPSTR_FOREGROUND_SERVICE_SPECIAL_USE,
+            OPSTR_SYSTEM_EXEMPT_FROM_POWER_RESTRICTIONS,
+            OPSTR_SYSTEM_EXEMPT_FROM_HIBERNATION,
+            OPSTR_SYSTEM_EXEMPT_FROM_ACTIVITY_BG_START_RESTRICTION,
+            OPSTR_CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD,
+            OPSTR_BODY_SENSORS_WRIST_TEMPERATURE,
+            OPSTR_USE_FULL_SCREEN_INTENT,
+    })
+    public @interface AppOpString {}
+
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
     /** Access to fine location information. */
@@ -7736,18 +7880,19 @@
     }
 
     /**
-     * Start watching for noted app ops. An app op may be immediate or long running.
-     * Immediate ops are noted while long running ones are started and stopped. This
-     * method allows registering a listener to be notified when an app op is noted. If
-     * an op is being noted by any package you will get a callback. To change the
-     * watched ops for a registered callback you need to unregister and register it again.
+     * Start watching for noted app ops.
      *
-     * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission
-     * you can watch changes only for your UID.
+     * <p> Similar to {@link #startWatchingNoted(String[], Executor, OnOpNotedListener)}, but
+     * without an executor parameter.
      *
-     * @param ops The ops to watch.
-     * @param callback Where to report changes.
+     * <p> Note that the listener will be called on the main thread using
+     * {@link Context.getMainThread()}. To specify the execution thread, use
+     * {@link #startWatchingNoted(String[], Executor, OnOpNotedListener)}.
      *
+     * @param ops      the ops to watch
+     * @param listener listener to notify when an app op is noted
+     *
+     * @see #startWatchingNoted(String[], Executor, OnOpNotedListener)
      * @see #stopWatchingNoted(OnOpNotedListener)
      * @see #noteOp(String, int, String, String, String)
      *
@@ -7755,40 +7900,111 @@
      */
     @SystemApi
     @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
-    public void startWatchingNoted(@NonNull String[] ops, @NonNull OnOpNotedListener callback) {
+    public void startWatchingNoted(@NonNull @AppOpString String[] ops,
+     @NonNull OnOpNotedListener listener) {
         final int[] intOps = new int[ops.length];
         for (int i = 0; i < ops.length; i++) {
             intOps[i] = strOpToOp(ops[i]);
         }
-        startWatchingNoted(intOps, callback);
+        startWatchingNoted(intOps, listener);
     }
 
     /**
-     * Start watching for noted app ops. An app op may be immediate or long running.
-     * Immediate ops are noted while long running ones are started and stopped. This
-     * method allows registering a listener to be notified when an app op is noted. If
-     * an op is being noted by any package you will get a callback. To change the
-     * watched ops for a registered callback you need to unregister and register it again.
+     * Start watching for noted app ops.
      *
-     * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission
-     * you can watch changes only for your UID.
+     * <p> An app op may be immediate or long-running. Immediate ops are noted while long-running
+     * ones are started and stopped.
      *
-     * This allows observing noted ops by their raw op codes instead of string op names.
+     * <p> This method allows registering a listener to be notified when an app op is noted. To
+     * change the watched ops for a registered callback you need to unregister and register it
+     * again.
      *
-     * @param ops The ops to watch.
-     * @param callback Where to report changes.
+     * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission you can
+     * watch changes only for your UID.
+     *
+     * @param ops      the ops to watch
+     * @param executor the executor on which the listener will be notified
+     * @param listener listener to notify when an app op is noted
+     *
+     * @see #startWatchingNoted(String[], OnOpNotedListener)
+     * @see #stopWatchingNoted(OnOpNotedListener)
+     * @see #noteOp(String, int, String, String, String)
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
+    public void startWatchingNoted(@NonNull @AppOpString String[] ops,
+     @CallbackExecutor @NonNull Executor executor, @NonNull OnOpNotedListener listener) {
+        final int[] intOps = new int[ops.length];
+        for (int i = 0; i < ops.length; i++) {
+            intOps[i] = strOpToOp(ops[i]);
+        }
+        startWatchingNoted(intOps, executor, listener);
+    }
+
+    /**
+     * Start watching for noted app ops.
+     *
+     * <p> Similar to {@link #startWatchingNoted(int[], Executor, OnOpNotedListener)}, but without
+     * an executor parameter.
+     *
+     * <p> This method is also similar to {@link #startWatchingNoted(String[], OnOpNotedListener)},
+     * but allows observing noted ops by their raw op codes instead of string op names.
+     *
+     * <p> Note that the listener will be called on the main thread using
+     * {@link Context.getMainThread()}. To specify the execution thread, use
+     * {@link {@link #startWatchingNoted(String[], Executor, OnOpNotedListener)}.
+     *
+     * @param ops      the ops to watch
+     * @param listener listener to notify when an app op is noted
      *
      * @see #startWatchingActive(int[], OnOpActiveChangedListener)
      * @see #startWatchingStarted(int[], OnOpStartedListener)
      * @see #startWatchingNoted(String[], OnOpNotedListener)
+     * @see #startWatchingNoted(int[], Executor, OnOpNotedListener)
+     *
+     * @hide
+     */
+    @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
+    public void startWatchingNoted(@NonNull int[] ops, @NonNull OnOpNotedListener listener) {
+        startWatchingNoted(ops, mContext.getMainExecutor(), listener);
+    }
+
+    /**
+     * Start watching for noted app ops.
+     *
+     * <p> This method is similar to
+     * {@link #startWatchingNoted(String[], Executor, OnOpNotedListener)}, but allows observing
+     * noted ops by their raw op codes instead of string op names.
+     *
+     * <p> An app op may be immediate or long-running. Immediate ops are noted while long-running
+     * ones are started and stopped.
+     *
+     * <p> This method allows registering a listener to be notified when an app op is noted. To
+     * change the watched ops for a registered callback you need to unregister and register it
+     * again.
+     *
+     * <p> If you don't hold the {@link android.Manifest.permission#WATCH_APPOPS} permission you
+     * can watch changes only for your UID.
+     *
+     * @param ops      the ops to watch
+     * @param executor the executor on which the listener will be notified
+     * @param listener listener to notify when an app op is noted
+     *
+     * @see #startWatchingActive(int[], OnOpActiveChangedListener)
+     * @see #startWatchingStarted(int[], OnOpStartedListener)
+     * @see #startWatchingNoted(int[], Executor, OnOpNotedListener)
+     * @see #startWatchingNoted(String[], OnOpNotedListener)
      *
      * @hide
      */
     @RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
-    public void startWatchingNoted(@NonNull int[] ops, @NonNull OnOpNotedListener callback) {
+    public void startWatchingNoted(@NonNull int[] ops,
+     @CallbackExecutor @NonNull Executor executor, @NonNull OnOpNotedListener listener) {
         IAppOpsNotedCallback cb;
         synchronized (mNotedWatchers) {
-            cb = mNotedWatchers.get(callback);
+            cb = mNotedWatchers.get(listener);
             if (cb != null) {
                 return;
             }
@@ -7796,13 +8012,21 @@
                 @Override
                 public void opNoted(int op, int uid, String packageName, String attributionTag,
                         int flags, int mode) {
-                    if (sAppOpInfos[op].name != null) {
-                        callback.onOpNoted(sAppOpInfos[op].name, uid, packageName, attributionTag,
-                                flags, mode);
+                    final long identity = Binder.clearCallingIdentity();
+                    try {
+                        executor.execute(() -> {
+                            if (sAppOpInfos[op].name != null) {
+                                listener.onOpNoted(sAppOpInfos[op].name, uid, packageName,
+                                        attributionTag,
+                                        flags, mode);
+                            }
+                        });
+                    } finally {
+                        Binder.restoreCallingIdentity(identity);
                     }
                 }
             };
-            mNotedWatchers.put(callback, cb);
+            mNotedWatchers.put(listener, cb);
         }
         try {
             mService.startWatchingNoted(ops, cb);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index a99815c..6301ad7 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -556,12 +556,7 @@
     @Override
     public ActivityInfo getActivityInfo(ComponentName className, ComponentInfoFlags flags)
             throws NameNotFoundException {
-        return getActivityInfoAsUser(className, flags, getUserId());
-    }
-
-    @Override
-    public ActivityInfo getActivityInfoAsUser(ComponentName className,
-            ComponentInfoFlags flags, @UserIdInt int userId) throws NameNotFoundException {
+        final int userId = getUserId();
         try {
             ActivityInfo ai = mPM.getActivityInfo(className,
                     updateFlagsForComponent(flags.getValue(), userId, null), userId);
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index fe40a4c..f48181b 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -60,7 +60,6 @@
     private String[] mRequireNoneOfPermissions;
     private long mRequireCompatChangeId = CHANGE_INVALID;
     private long mIdForResponseEvent;
-    private @Nullable IntentFilter mRemoveMatchingFilter;
     private @DeliveryGroupPolicy int mDeliveryGroupPolicy;
     private @Nullable String mDeliveryGroupMatchingKey;
     private @Nullable BundleMerger mDeliveryGroupExtrasMerger;
@@ -190,12 +189,6 @@
             "android:broadcast.idForResponseEvent";
 
     /**
-     * Corresponds to {@link #setRemoveMatchingFilter}.
-     */
-    private static final String KEY_REMOVE_MATCHING_FILTER =
-            "android:broadcast.removeMatchingFilter";
-
-    /**
      * Corresponds to {@link #setDeliveryGroupPolicy(int)}.
      */
     private static final String KEY_DELIVERY_GROUP_POLICY =
@@ -274,18 +267,6 @@
     }
 
     /**
-     * {@hide}
-     * @deprecated use {@link #setDeliveryGroupMatchingFilter(IntentFilter)} instead.
-     */
-    @Deprecated
-    public static @NonNull BroadcastOptions makeRemovingMatchingFilter(
-            @NonNull IntentFilter removeMatchingFilter) {
-        BroadcastOptions opts = new BroadcastOptions();
-        opts.setRemoveMatchingFilter(removeMatchingFilter);
-        return opts;
-    }
-
-    /**
      * Creates a new {@code BroadcastOptions} with no options initially set.
      */
     public BroadcastOptions() {
@@ -315,8 +296,6 @@
         mRequireNoneOfPermissions = opts.getStringArray(KEY_REQUIRE_NONE_OF_PERMISSIONS);
         mRequireCompatChangeId = opts.getLong(KEY_REQUIRE_COMPAT_CHANGE_ID, CHANGE_INVALID);
         mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT);
-        mRemoveMatchingFilter = opts.getParcelable(KEY_REMOVE_MATCHING_FILTER,
-                IntentFilter.class);
         mDeliveryGroupPolicy = opts.getInt(KEY_DELIVERY_GROUP_POLICY,
                 DELIVERY_GROUP_POLICY_ALL);
         mDeliveryGroupMatchingKey = opts.getString(KEY_DELIVERY_GROUP_KEY);
@@ -797,31 +776,6 @@
     }
 
     /**
-     * When enqueuing this broadcast, remove all pending broadcasts previously
-     * sent by this app which match the given filter.
-     * <p>
-     * For example, sending {@link Intent#ACTION_SCREEN_ON} would typically want
-     * to remove any pending {@link Intent#ACTION_SCREEN_OFF} broadcasts.
-     *
-     * @hide
-     * @deprecated use {@link #setDeliveryGroupMatchingFilter(IntentFilter)} instead.
-     */
-    @Deprecated
-    public void setRemoveMatchingFilter(@NonNull IntentFilter removeMatchingFilter) {
-        mRemoveMatchingFilter = Objects.requireNonNull(removeMatchingFilter);
-    }
-
-    /** @hide */
-    public void clearRemoveMatchingFilter() {
-        mRemoveMatchingFilter = null;
-    }
-
-    /** @hide */
-    public @Nullable IntentFilter getRemoveMatchingFilter() {
-        return mRemoveMatchingFilter;
-    }
-
-    /**
      * Set delivery group policy for this broadcast to specify how multiple broadcasts belonging to
      * the same delivery group has to be handled.
      *
@@ -1092,9 +1046,6 @@
         if (mIdForResponseEvent != 0) {
             b.putLong(KEY_ID_FOR_RESPONSE_EVENT, mIdForResponseEvent);
         }
-        if (mRemoveMatchingFilter != null) {
-            b.putParcelable(KEY_REMOVE_MATCHING_FILTER, mRemoveMatchingFilter);
-        }
         if (mDeliveryGroupPolicy != DELIVERY_GROUP_POLICY_ALL) {
             b.putInt(KEY_DELIVERY_GROUP_POLICY, mDeliveryGroupPolicy);
         }
diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java
index 6bb38e7..49fb794 100644
--- a/core/java/android/app/ClientTransactionHandler.java
+++ b/core/java/android/app/ClientTransactionHandler.java
@@ -188,7 +188,7 @@
 
     /** Perform activity launch. */
     public abstract Activity handleLaunchActivity(@NonNull ActivityClientRecord r,
-            PendingTransactionActions pendingActions, Intent customIntent);
+            PendingTransactionActions pendingActions, int deviceId, Intent customIntent);
 
     /** Perform activity start. */
     public abstract void handleStartActivity(@NonNull ActivityClientRecord r,
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1c0be68..4713a31 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -245,7 +245,7 @@
     @UnsupportedAppUsage
     private @NonNull Resources mResources;
     private @Nullable Display mDisplay; // may be null if invalid display or not initialized yet.
-    private int mDeviceId = VirtualDeviceManager.DEVICE_ID_DEFAULT;
+    private int mDeviceId = Context.DEVICE_ID_DEFAULT;
 
     /**
      * If set to {@code true} the resources for this context will be configured for mDisplay which
@@ -2812,9 +2812,9 @@
 
     @Override
     public @NonNull Context createDeviceContext(int deviceId) {
-        if (deviceId != VirtualDeviceManager.DEVICE_ID_DEFAULT) {
+        if (deviceId != Context.DEVICE_ID_DEFAULT) {
             VirtualDeviceManager vdm = getSystemService(VirtualDeviceManager.class);
-            if (!vdm.isValidVirtualDeviceId(deviceId)) {
+            if (vdm == null || !vdm.isValidVirtualDeviceId(deviceId)) {
                 throw new IllegalArgumentException(
                         "Not a valid ID of the default device or any virtual device: " + deviceId);
             }
@@ -3092,7 +3092,7 @@
 
     @Override
     public void updateDeviceId(int updatedDeviceId) {
-        if (updatedDeviceId != VirtualDeviceManager.DEVICE_ID_DEFAULT) {
+        if (updatedDeviceId != Context.DEVICE_ID_DEFAULT) {
             VirtualDeviceManager vdm = getSystemService(VirtualDeviceManager.class);
             if (!vdm.isValidVirtualDeviceId(updatedDeviceId)) {
                 throw new IllegalArgumentException(
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index f653e13..5c38c42 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -341,12 +341,6 @@
             in String message, boolean force, int exceptionTypeId);
     void crashApplicationWithTypeWithExtras(int uid, int initialPid, in String packageName,
             int userId, in String message, boolean force, int exceptionTypeId, in Bundle extras);
-    /** @deprecated -- use getProviderMimeTypeAsync */
-    @UnsupportedAppUsage(maxTargetSdk = 29, publicAlternatives =
-            "Use {@link android.content.ContentResolver#getType} public API instead.")
-    String getProviderMimeType(in Uri uri, int userId);
-
-    oneway void getProviderMimeTypeAsync(in Uri uri, int userId, in RemoteCallback resultCallback);
     oneway void getMimeTypeFilterAsync(in Uri uri, int userId, in RemoteCallback resultCallback);
     // Cause the specified process to dump the specified heap.
     boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
diff --git a/core/java/android/app/LocaleConfig.java b/core/java/android/app/LocaleConfig.java
index 69693fc..f4cd60d 100644
--- a/core/java/android/app/LocaleConfig.java
+++ b/core/java/android/app/LocaleConfig.java
@@ -38,7 +38,10 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Locale;
 import java.util.Set;
 
@@ -263,6 +266,43 @@
             };
 
     /**
+     * Compare whether the LocaleConfig is the same.
+     *
+     * <p>If the elements of {@code mLocales} in LocaleConfig are the same but arranged in different
+     * positions, they are also considered to be the same LocaleConfig.
+     *
+     * @param other The {@link LocaleConfig} to compare for.
+     *
+     * @return true if the LocaleConfig is the same, false otherwise.
+     *
+     * @hide
+     */
+    public boolean isSameLocaleConfig(@Nullable LocaleConfig other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (other != null) {
+            if (mStatus != other.mStatus) {
+                return false;
+            }
+            LocaleList otherLocales = other.mLocales;
+            if (mLocales == null && otherLocales == null) {
+                return true;
+            } else if (mLocales != null && otherLocales != null) {
+                List<String> hostStrList = Arrays.asList(mLocales.toLanguageTags().split(","));
+                List<String> targetStrList = Arrays.asList(
+                        otherLocales.toLanguageTags().split(","));
+                Collections.sort(hostStrList);
+                Collections.sort(targetStrList);
+                return hostStrList.equals(targetStrList);
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Compare whether the locale is existed in the {@code mLocales} of the LocaleConfig.
      *
      * @param locale The {@link Locale} to compare for.
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 91efa75..d2f2c3c 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -873,7 +873,7 @@
      * permission to your manifest, and use
      * {@link android.provider.Settings#ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT}.
      */
-    public boolean canSendFullScreenIntent() {
+    public boolean canUseFullScreenIntent() {
         final int result = PermissionChecker.checkPermissionForPreflight(mContext,
                 android.Manifest.permission.USE_FULL_SCREEN_INTENT,
                 mContext.getAttributionSource());
diff --git a/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java b/core/java/android/app/StartForegroundCalledOnStoppedServiceException.java
new file mode 100644
index 0000000..55885a6
--- /dev/null
+++ b/core/java/android/app/StartForegroundCalledOnStoppedServiceException.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 android.app;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Exception thrown when {@link Service#startForeground} is called on a service that's not
+ * actually started.
+ */
+public final class StartForegroundCalledOnStoppedServiceException
+        extends IllegalStateException implements Parcelable {
+    /**
+     * Constructor.
+     */
+    public StartForegroundCalledOnStoppedServiceException(@NonNull String message) {
+        super(message);
+    }
+
+    StartForegroundCalledOnStoppedServiceException(@NonNull Parcel source) {
+        super(source.readString());
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(getMessage());
+    }
+
+    public static final @NonNull Creator<StartForegroundCalledOnStoppedServiceException>
+            CREATOR = new Creator<StartForegroundCalledOnStoppedServiceException>() {
+                @NonNull
+                public StartForegroundCalledOnStoppedServiceException createFromParcel(
+                        Parcel source) {
+                    return new StartForegroundCalledOnStoppedServiceException(source);
+                }
+
+                @NonNull
+                public StartForegroundCalledOnStoppedServiceException[] newArray(int size) {
+                    return new StartForegroundCalledOnStoppedServiceException[size];
+                }
+            };
+}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6d80a44..83e0153 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -877,6 +877,10 @@
             @Override
             public VirtualDeviceManager createService(ContextImpl ctx)
                     throws ServiceNotFoundException {
+                if (!ctx.getPackageManager().hasSystemFeature(
+                        PackageManager.FEATURE_COMPANION_DEVICE_SETUP)) {
+                    return null;
+                }
                 IVirtualDeviceManager service = IVirtualDeviceManager.Stub.asInterface(
                         ServiceManager.getServiceOrThrow(Context.VIRTUAL_DEVICE_SERVICE));
                 return new VirtualDeviceManager(service, ctx.getOuterContext());
@@ -1648,6 +1652,7 @@
                 case Context.ETHERNET_SERVICE:
                 case Context.CONTEXTHUB_SERVICE:
                 case Context.VIRTUALIZATION_SERVICE:
+                case Context.VIRTUAL_DEVICE_SERVICE:
                     return null;
             }
             Slog.wtf(TAG, "Manager wrapper not available: " + name);
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 5a2f261..303ada0 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -453,6 +453,7 @@
                 && Objects.equals(shouldDockBigOverlays, that.shouldDockBigOverlays)
                 && Objects.equals(displayCutoutInsets, that.displayCutoutInsets)
                 && getWindowingMode() == that.getWindowingMode()
+                && configuration.uiMode == that.configuration.uiMode
                 && Objects.equals(taskDescription, that.taskDescription)
                 && isFocused == that.isFocused
                 && isVisible == that.isVisible
@@ -481,6 +482,7 @@
                     .equals(that.configuration.windowConfiguration.getBounds()))
                 && (!hasCompatUI() || configuration.getLayoutDirection()
                     == that.configuration.getLayoutDirection())
+                && (!hasCompatUI() || configuration.uiMode == that.configuration.uiMode)
                 && (!hasCompatUI() || isVisible == that.isVisible);
     }
 
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index e750f49..5848521 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -1091,7 +1091,6 @@
      *
      * @hide
      */
-    @NonNull
     @SystemApi
     public void reportDelayedRestoreResult(@NonNull BackupRestoreEventLogger logger) {
         checkServiceBinder();
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index f56c8c3..dcac59c 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -656,11 +656,14 @@
     }
 
     /**
-     * Ask the transport for a {@link IBackupManagerMonitor} instance which will be used by the
+     * Ask the transport for a {@link BackupManagerMonitor} instance which will be used by the
      * framework to report logging events back to the transport.
      *
      * <p>Backups requested from outside the framework may pass in a monitor with the request,
      * however backups initiated by the framework will call this method to retrieve one.
+     *
+     * @return {@link BackupManagerMonitor} or {@code null} if the transport implementation does not
+     *         wish to receive the logging events.
      */
     @Nullable
     public BackupManagerMonitor getBackupManagerMonitor() {
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 3d0aa25..5833f1b 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -96,11 +96,11 @@
             PendingTransactionActions pendingActions) {
         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
         ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
-                mOverrideConfig, mDeviceId, mReferrer, mVoiceInteractor, mState, mPersistentState,
+                mOverrideConfig, mReferrer, mVoiceInteractor, mState, mPersistentState,
                 mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
                 client, mAssistToken, mShareableActivityToken, mLaunchedFromBubble,
                 mTaskFragmentToken);
-        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
+        client.handleLaunchActivity(r, pendingActions, mDeviceId, null /* customIntent */);
         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
     }
 
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index c8f7d10..bfab61f 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -32,6 +32,7 @@
 
 import android.app.ActivityThread.ActivityClientRecord;
 import android.app.ClientTransactionHandler;
+import android.content.Context;
 import android.os.IBinder;
 import android.util.IntArray;
 import android.util.Slog;
@@ -218,7 +219,7 @@
             switch (state) {
                 case ON_CREATE:
                     mTransactionHandler.handleLaunchActivity(r, mPendingActions,
-                            null /* customIntent */);
+                            Context.DEVICE_ID_INVALID, null /* customIntent */);
                     break;
                 case ON_START:
                     mTransactionHandler.handleStartActivity(r, mPendingActions,
diff --git a/core/java/android/companion/virtual/VirtualDevice.java b/core/java/android/companion/virtual/VirtualDevice.java
index f3f43354..4a09186 100644
--- a/core/java/android/companion/virtual/VirtualDevice.java
+++ b/core/java/android/companion/virtual/VirtualDevice.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.Context;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -38,9 +39,9 @@
      * @hide
      */
     public VirtualDevice(int id, @Nullable String name) {
-        if (id <= VirtualDeviceManager.DEVICE_ID_DEFAULT) {
+        if (id <= Context.DEVICE_ID_DEFAULT) {
             throw new IllegalArgumentException("VirtualDevice ID mist be greater than "
-                    + VirtualDeviceManager.DEVICE_ID_DEFAULT);
+                    + Context.DEVICE_ID_DEFAULT);
         }
         mId = id;
         mName = name;
diff --git a/core/java/android/companion/virtual/VirtualDeviceManager.java b/core/java/android/companion/virtual/VirtualDeviceManager.java
index ae43c6e..6cc4c8a 100644
--- a/core/java/android/companion/virtual/VirtualDeviceManager.java
+++ b/core/java/android/companion/virtual/VirtualDeviceManager.java
@@ -89,24 +89,6 @@
 
     private static final String TAG = "VirtualDeviceManager";
 
-    private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS =
-            DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
-                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
-
-    /**
-     * The default device ID, which is the ID of the primary (non-virtual) device.
-     */
-    public static final int DEVICE_ID_DEFAULT = 0;
-
-    /**
-     * Invalid device ID.
-     */
-    public static final int DEVICE_ID_INVALID = -1;
-
     /**
      * Broadcast Action: A Virtual Device was removed.
      *
@@ -250,7 +232,7 @@
     public int getDeviceIdForDisplayId(int displayId) {
         if (mService == null) {
             Log.w(TAG, "Failed to retrieve virtual devices; no virtual device manager service.");
-            return DEVICE_ID_DEFAULT;
+            return Context.DEVICE_ID_DEFAULT;
         }
         try {
             return mService.getDeviceIdForDisplayId(displayId);
@@ -261,7 +243,7 @@
 
     /**
      * Checks whether the passed {@code deviceId} is a valid virtual device ID or not.
-     * {@link VirtualDeviceManager#DEVICE_ID_DEFAULT} is not valid as it is the ID of the default
+     * {@link Context#DEVICE_ID_DEFAULT} is not valid as it is the ID of the default
      * device which is not a virtual device. {@code deviceId} must correspond to a virtual device
      * created by {@link VirtualDeviceManager#createVirtualDevice(int, VirtualDeviceParams)}.
      *
@@ -549,7 +531,11 @@
          * not create the virtual display.
          *
          * @see DisplayManager#createVirtualDisplay
+         *
+         * @deprecated use {@link #createVirtualDisplay(VirtualDisplayConfig, Executor,
+         * VirtualDisplay.Callback)}
          */
+        @Deprecated
         @Nullable
         public VirtualDisplay createVirtualDisplay(
                 @IntRange(from = 1) int width,
@@ -562,30 +548,16 @@
             VirtualDisplayConfig config = new VirtualDisplayConfig.Builder(
                     getVirtualDisplayName(), width, height, densityDpi)
                     .setSurface(surface)
-                    .setFlags(getVirtualDisplayFlags(flags))
+                    .setFlags(flags)
                     .build();
-            return createVirtualDisplayInternal(config, executor, callback);
+            return createVirtualDisplay(config, executor, callback);
         }
 
         /**
          * Creates a virtual display for this virtual device. All displays created on the same
          * device belongs to the same display group.
          *
-         * @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 displayCategories The categories of the virtual display, indicating the type of
-         * activities allowed to run on the display. Activities can declare their type using
-         * {@link android.content.pm.ActivityInfo#requiredDisplayCategory}.
-         * @param surface The surface to which the content of the virtual display should
-         * be rendered, or null if there is none initially. The surface can also be set later using
-         * {@link VirtualDisplay#setSurface(Surface)}.
-         * @param flags A combination of virtual display flags accepted by
-         * {@link DisplayManager#createVirtualDisplay}. In addition, the following flags are
-         * automatically set for all virtual devices:
-         * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC VIRTUAL_DISPLAY_FLAG_PUBLIC} and
-         * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
-         * VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}.
+         * @param config The configuration of the display.
          * @param executor The executor on which {@code callback} will be invoked. This is ignored
          * if {@code callback} is {@code null}. If {@code callback} is specified, this executor must
          * not be null.
@@ -597,28 +569,6 @@
          */
         @Nullable
         public VirtualDisplay createVirtualDisplay(
-                @IntRange(from = 1) int width,
-                @IntRange(from = 1) int height,
-                @IntRange(from = 1) int densityDpi,
-                @NonNull List<String> displayCategories,
-                @Nullable Surface surface,
-                @VirtualDisplayFlag int flags,
-                @Nullable @CallbackExecutor Executor executor,
-                @Nullable VirtualDisplay.Callback callback) {
-            VirtualDisplayConfig config = new VirtualDisplayConfig.Builder(
-                    getVirtualDisplayName(), width, height, densityDpi)
-                    .setDisplayCategories(displayCategories)
-                    .setSurface(surface)
-                    .setFlags(getVirtualDisplayFlags(flags))
-                    .build();
-            return createVirtualDisplayInternal(config, executor, callback);
-        }
-
-        /**
-         * @hide
-         */
-        @Nullable
-        private VirtualDisplay createVirtualDisplayInternal(
                 @NonNull VirtualDisplayConfig config,
                 @Nullable @CallbackExecutor Executor executor,
                 @Nullable VirtualDisplay.Callback callback) {
@@ -907,16 +857,6 @@
             }
         }
 
-        /**
-         * Returns the display flags that should be added to a particular virtual display.
-         * Additional device-level flags from {@link
-         * com.android.server.companion.virtual.VirtualDeviceImpl#getBaseVirtualDisplayFlags()} will
-         * be added by DisplayManagerService.
-         */
-        private int getVirtualDisplayFlags(int flags) {
-            return DEFAULT_VIRTUAL_DISPLAY_FLAGS | flags;
-        }
-
         private String getVirtualDisplayName() {
             try {
                 // Currently this just use the device ID, which means all of the virtual displays
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index d8076b5..9f3b601 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -35,6 +35,7 @@
 import android.content.ComponentName;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SharedMemory;
 import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.SparseArray;
@@ -577,6 +578,25 @@
                 mExecutor.execute(() -> mCallback.onConfigurationChanged(
                         sensor, enabled, samplingPeriod, batchReportingLatency));
             }
+
+            @Override
+            public void onDirectChannelCreated(int channelHandle,
+                    @NonNull SharedMemory sharedMemory) {
+                mExecutor.execute(
+                        () -> mCallback.onDirectChannelCreated(channelHandle, sharedMemory));
+            }
+
+            @Override
+            public void onDirectChannelDestroyed(int channelHandle) {
+                mExecutor.execute(() -> mCallback.onDirectChannelDestroyed(channelHandle));
+            }
+
+            @Override
+            public void onDirectChannelConfigured(int channelHandle, @NonNull VirtualSensor sensor,
+                    int rateLevel, int reportToken) {
+                mExecutor.execute(() -> mCallback.onDirectChannelConfigured(
+                        channelHandle, sensor, rateLevel, reportToken));
+            }
         }
 
         /**
diff --git a/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl b/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl
index 7da9c32..3cb0572 100644
--- a/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl
+++ b/core/java/android/companion/virtual/sensor/IVirtualSensorCallback.aidl
@@ -17,6 +17,7 @@
 package android.companion.virtual.sensor;
 
 import android.companion.virtual.sensor.VirtualSensor;
+import android.os.SharedMemory;
 
 /**
  * Interface for notifying the sensor owner about whether and how sensor events should be injected.
@@ -36,4 +37,31 @@
      */
     void onConfigurationChanged(in VirtualSensor sensor, boolean enabled, int samplingPeriodMicros,
             int batchReportLatencyMicros);
+
+    /**
+     * Called when a sensor direct channel is created.
+     *
+     * @param channelHandle Identifier of the channel that was created.
+     * @param sharedMemory The shared memory region for the direct sensor channel.
+     */
+    void onDirectChannelCreated(int channelHandle, in SharedMemory sharedMemory);
+
+    /**
+     * Called when a sensor direct channel is destroyed.
+     *
+     * @param channelHandle Identifier of the channel that was destroyed.
+     */
+    void onDirectChannelDestroyed(int channelHandle);
+
+    /**
+     * Called when a sensor direct channel is configured.
+     *
+     * @param channelHandle Identifier of the channel that was configured.
+     * @param sensor The sensor, for which the channel was configured.
+     * @param rateLevel The rate level used to configure the direct sensor channel.
+     * @param reportToken A positive sensor report token, used to differentiate between events from
+     * different sensors within the same channel.
+     */
+    void onDirectChannelConfigured(int channelHandle, in VirtualSensor sensor, int rateLevel,
+            int reportToken);
 }
diff --git a/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java b/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java
index e097189..f7af283 100644
--- a/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java
+++ b/core/java/android/companion/virtual/sensor/VirtualSensorCallback.java
@@ -17,8 +17,13 @@
 package android.companion.virtual.sensor;
 
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.hardware.Sensor;
+import android.hardware.SensorDirectChannel;
+import android.os.MemoryFile;
+import android.os.SharedMemory;
 
 import java.time.Duration;
 
@@ -50,4 +55,74 @@
      */
     void onConfigurationChanged(@NonNull VirtualSensor sensor, boolean enabled,
             @NonNull Duration samplingPeriod, @NonNull Duration batchReportLatency);
+
+    /**
+     * Called when a {@link android.hardware.SensorDirectChannel} is created.
+     *
+     * <p>The {@link android.hardware.SensorManager} instance used to create the direct channel must
+     * be associated with the virtual device.
+     *
+     * <p>A typical order of callback invocations is:
+     * <ul>
+     *     <li>{@code onDirectChannelCreated} - the channel handle and the associated shared memory
+     *     should be stored by the virtual device</li>
+     *     <li>{@code onDirectChannelConfigured} with a positive {@code rateLevel} - the virtual
+     *     device should start writing to the shared memory for the associated channel with the
+     *     requested parameters.</li>
+     *     <li>{@code onDirectChannelConfigured} with a {@code rateLevel = RATE_STOP} - the virtual
+     *     device should stop writing to the shared memory for the associated channel.</li>
+     *     <li>{@code onDirectChannelDestroyed} - the shared memory associated with the channel
+     *     handle should be closed.</li>
+     * </ul>
+     *
+     * @param channelHandle Identifier of the newly created channel.
+     * @param sharedMemory writable shared memory region.
+     *
+     * @see android.hardware.SensorManager#createDirectChannel(MemoryFile)
+     * @see #onDirectChannelConfigured
+     * @see #onDirectChannelDestroyed
+     */
+    default void onDirectChannelCreated(@IntRange(from = 1) int channelHandle,
+            @NonNull SharedMemory sharedMemory) {}
+
+    /**
+     * Called when a {@link android.hardware.SensorDirectChannel} is destroyed.
+     *
+     * <p>The virtual device must perform any clean-up and close the shared memory that was
+     * received with the {@link #onDirectChannelCreated} callback and the corresponding
+     * {@code channelHandle}.
+     *
+     * @param channelHandle Identifier of the channel that was destroyed.
+     *
+     * @see SensorDirectChannel#close()
+     */
+    default void onDirectChannelDestroyed(@IntRange(from = 1) int channelHandle) {}
+
+    /**
+     * Called when a {@link android.hardware.SensorDirectChannel} is configured.
+     *
+     * <p>Sensor events for the corresponding sensor should be written at the indicated rate to the
+     * shared memory region that was received with the {@link #onDirectChannelCreated} callback and
+     * the corresponding {@code channelHandle}. The events should be written in the correct format
+     * and with the provided {@code reportToken} until the channel is reconfigured with
+     * {@link SensorDirectChannel#RATE_STOP}.
+     *
+     * <p>The sensor must support direct channel in order for this callback to be invoked. Only
+     * {@link MemoryFile} sensor direct channels are supported for virtual sensors.
+     *
+     * @param channelHandle Identifier of the channel that was configured.
+     * @param sensor The sensor, for which the channel was configured.
+     * @param rateLevel The rate level used to configure the direct sensor channel.
+     * @param reportToken A positive sensor report token, used to differentiate between events from
+     * different sensors within the same channel.
+     *
+     * @see VirtualSensorConfig.Builder#setHighestDirectReportRateLevel(int)
+     * @see VirtualSensorConfig.Builder#setDirectChannelTypesSupported(int)
+     * @see android.hardware.SensorManager#createDirectChannel(MemoryFile)
+     * @see #onDirectChannelCreated
+     * @see SensorDirectChannel#configure(Sensor, int)
+     */
+    default void onDirectChannelConfigured(@IntRange(from = 1) int channelHandle,
+            @NonNull VirtualSensor sensor, @SensorDirectChannel.RateLevel int rateLevel,
+            @IntRange(from = 1) int reportToken) {}
 }
diff --git a/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java b/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
index 6d45365..ffbdff8 100644
--- a/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
+++ b/core/java/android/companion/virtual/sensor/VirtualSensorConfig.java
@@ -21,11 +21,13 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.hardware.Sensor;
+import android.hardware.SensorDirectChannel;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import java.util.Objects;
 
+
 /**
  * Configuration for creation of a virtual sensor.
  * @see VirtualSensor
@@ -33,6 +35,14 @@
  */
 @SystemApi
 public final class VirtualSensorConfig implements Parcelable {
+    private static final String TAG = "VirtualSensorConfig";
+
+    // Mask for direct mode highest rate level, bit 7, 8, 9.
+    private static final int DIRECT_REPORT_MASK = 0x380;
+    private static final int DIRECT_REPORT_SHIFT = 7;
+
+    // Mask for supported direct channel, bit 10, 11
+    private static final int DIRECT_CHANNEL_SHIFT = 10;
 
     private final int mType;
     @NonNull
@@ -40,16 +50,21 @@
     @Nullable
     private final String mVendor;
 
-    private VirtualSensorConfig(int type, @NonNull String name, @Nullable String vendor) {
+    private final int mFlags;
+
+    private VirtualSensorConfig(int type, @NonNull String name, @Nullable String vendor,
+            int flags) {
         mType = type;
         mName = name;
         mVendor = vendor;
+        mFlags = flags;
     }
 
     private VirtualSensorConfig(@NonNull Parcel parcel) {
         mType = parcel.readInt();
         mName = parcel.readString8();
         mVendor = parcel.readString8();
+        mFlags = parcel.readInt();
     }
 
     @Override
@@ -62,6 +77,7 @@
         parcel.writeInt(mType);
         parcel.writeString8(mName);
         parcel.writeString8(mVendor);
+        parcel.writeInt(mFlags);
     }
 
     /**
@@ -92,22 +108,64 @@
     }
 
     /**
+     * Returns the highest supported direct report mode rate level of the sensor.
+     *
+     * @see Sensor#getHighestDirectReportRateLevel()
+     */
+    @SensorDirectChannel.RateLevel
+    public int getHighestDirectReportRateLevel() {
+        int rateLevel = ((mFlags & DIRECT_REPORT_MASK) >> DIRECT_REPORT_SHIFT);
+        return rateLevel <= SensorDirectChannel.RATE_VERY_FAST
+                ? rateLevel : SensorDirectChannel.RATE_VERY_FAST;
+    }
+
+    /**
+     * Returns a combination of all supported direct channel types.
+     *
+     * @see Builder#setDirectChannelTypesSupported(int)
+     * @see Sensor#isDirectChannelTypeSupported(int)
+     */
+    public @SensorDirectChannel.MemoryType int getDirectChannelTypesSupported() {
+        int memoryTypes = 0;
+        if ((mFlags & (1 << DIRECT_CHANNEL_SHIFT)) > 0) {
+            memoryTypes |= SensorDirectChannel.TYPE_MEMORY_FILE;
+        }
+        if ((mFlags & (1 << (DIRECT_CHANNEL_SHIFT + 1))) > 0) {
+            memoryTypes |= SensorDirectChannel.TYPE_HARDWARE_BUFFER;
+        }
+        return memoryTypes;
+    }
+
+    /**
+     * Returns the sensor flags.
+     * @hide
+     */
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /**
      * Builder for {@link VirtualSensorConfig}.
      */
     public static final class Builder {
 
+        private static final int FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED =
+                1 << DIRECT_CHANNEL_SHIFT;
         private final int mType;
         @NonNull
         private final String mName;
         @Nullable
         private String mVendor;
+        private int mFlags;
+        @SensorDirectChannel.RateLevel
+        int mHighestDirectReportRateLevel;
 
         /**
          * Creates a new builder.
          *
          * @param type The type of the sensor, matching {@link Sensor#getType}.
          * @param name The name of the sensor. Must be unique among all sensors with the same type
-         * that belong to the same virtual device.
+         *             that belong to the same virtual device.
          */
         public Builder(int type, @NonNull String name) {
             mType = type;
@@ -119,7 +177,19 @@
          */
         @NonNull
         public VirtualSensorConfig build() {
-            return new VirtualSensorConfig(mType, mName, mVendor);
+            if (mHighestDirectReportRateLevel > 0) {
+                if ((mFlags & FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED) == 0) {
+                    throw new IllegalArgumentException("Setting direct channel type is required "
+                            + "for sensors with direct channel support.");
+                }
+                mFlags |= mHighestDirectReportRateLevel << DIRECT_REPORT_SHIFT;
+            }
+            if ((mFlags & FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED) > 0
+                    && mHighestDirectReportRateLevel == 0) {
+                throw new IllegalArgumentException("Highest direct report rate level is "
+                        + "required for sensors with direct channel support.");
+            }
+            return new VirtualSensorConfig(mType, mName, mVendor, mFlags);
         }
 
         /**
@@ -130,6 +200,44 @@
             mVendor = vendor;
             return this;
         }
+
+        /**
+         * Sets the highest supported rate level for direct sensor report.
+         *
+         * @see VirtualSensorConfig#getHighestDirectReportRateLevel()
+         */
+        @NonNull
+        public VirtualSensorConfig.Builder setHighestDirectReportRateLevel(
+                @SensorDirectChannel.RateLevel int rateLevel) {
+            mHighestDirectReportRateLevel = rateLevel;
+            return this;
+        }
+
+        /**
+         * Sets whether direct sensor channel of the given types is supported.
+         *
+         * @param memoryTypes A combination of {@link SensorDirectChannel.MemoryType} flags
+         * indicating the types of shared memory supported for creating direct channels. Only
+         * {@link SensorDirectChannel#TYPE_MEMORY_FILE} direct channels may be supported for virtual
+         * sensors.
+         * @throws IllegalArgumentException if {@link SensorDirectChannel#TYPE_HARDWARE_BUFFER} is
+         * set to be supported.
+         */
+        @NonNull
+        public VirtualSensorConfig.Builder setDirectChannelTypesSupported(
+                @SensorDirectChannel.MemoryType int memoryTypes) {
+            if ((memoryTypes & SensorDirectChannel.TYPE_MEMORY_FILE) > 0) {
+                mFlags |= FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED;
+            } else {
+                mFlags &= ~FLAG_MEMORY_FILE_DIRECT_CHANNEL_SUPPORTED;
+            }
+            if ((memoryTypes & ~SensorDirectChannel.TYPE_MEMORY_FILE) > 0) {
+                throw new IllegalArgumentException(
+                        "Only TYPE_MEMORY_FILE direct channels can be supported for virtual "
+                                + "sensors.");
+            }
+            return this;
+        }
     }
 
     @NonNull
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 795c77f..d3502c5 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -389,6 +389,8 @@
 
         @Override
         public void getTypeAnonymousAsync(Uri uri, RemoteCallback callback) {
+            uri = validateIncomingUri(uri);
+            uri = maybeGetUriWithoutUserId(uri);
             final Bundle result = new Bundle();
             try {
                 result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getTypeAnonymous(uri));
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4dccc8d..d0accb7 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -135,6 +135,15 @@
     @VisibleForTesting
     public static final long OVERRIDABLE_COMPONENT_CALLBACKS = 193247900L;
 
+    /**
+     * The default device ID, which is the ID of the primary (non-virtual) device.
+     */
+    public static final int DEVICE_ID_DEFAULT = 0;
+    /**
+     * Invalid device ID.
+     */
+    public static final int DEVICE_ID_INVALID = -1;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "MODE_" }, value = {
             MODE_PRIVATE,
@@ -4267,7 +4276,7 @@
      * <p>Note: When implementing this method, keep in mind that new services can be added on newer
      * Android releases, so if you're looking for just the explicit names mentioned above, make sure
      * to return {@code null} when you don't recognize the name &mdash; if you throw a
-     * {@link RuntimeException} exception instead, you're app might break on new Android releases.
+     * {@link RuntimeException} exception instead, your app might break on new Android releases.
      *
      * @param name The name of the desired service.
      *
@@ -5694,6 +5703,9 @@
      * Use with {@link #getSystemService(String)} to retrieve a
      * {@link android.companion.virtual.VirtualDeviceManager} for managing virtual devices.
      *
+     * On devices without {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP}
+     * system feature the {@link #getSystemService(String)} will return {@code null}.
+     *
      * @see #getSystemService(String)
      * @see android.companion.virtual.VirtualDeviceManager
      */
@@ -7175,7 +7187,7 @@
      * <p>
      * Applications that run on virtual devices may use this method to access the default device
      * capabilities and functionality (by passing
-     * {@link android.companion.virtual.VirtualDeviceManager#DEVICE_ID_DEFAULT}. Similarly,
+     * {@link Context#DEVICE_ID_DEFAULT}. Similarly,
      * applications running on the default device may access the functionality of virtual devices.
      * </p>
      * <p>
@@ -7542,7 +7554,7 @@
      * determine whether they are running on a virtual device and identify that device.
      *
      * The device ID of the host device is
-     * {@link android.companion.virtual.VirtualDeviceManager#DEVICE_ID_DEFAULT}
+     * {@link Context#DEVICE_ID_DEFAULT}
      *
      * <p>
      * If the underlying device ID is changed by the system, for example, when an
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index bd3cf5f..afc2285 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -20,9 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
-import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledAfter;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.net.Uri;
 import android.os.Build;
@@ -185,28 +182,6 @@
     private static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
 
     /**
-     * An intent with action set as null used to always pass the action test during intent
-     * filter matching. This causes a lot of confusion and unexpected intent matches.
-     * Null action intents should be blocked when either the intent sender or receiver
-     * application targets U or higher.
-     *
-     * mBlockNullAction indicates whether the intent filter owner (intent receiver) is
-     * targeting U+. This value will be properly set by package manager when IntentFilters are
-     * passed to an application, so that when an application is trying to perform intent filter
-     * matching locally, the correct matching algorithm will be chosen.
-     *
-     * When an IntentFilter is sent to system server (e.g. for registering runtime receivers),
-     * the value set in mBlockNullAction will be ignored and overwritten with the correct
-     * value evaluated based on the Binder calling identity. This makes sure that the
-     * security enforcement cannot be bypassed by crafting a malicious IntentFilter.
-     *
-     * @hide
-     */
-    @ChangeId
-    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
-    public static final long BLOCK_NULL_ACTION_INTENTS = 264497795;
-
-    /**
      * The filter {@link #setPriority} value at which system high-priority
      * receivers are placed; that is, receivers that should execute before
      * application code. Applications should never use filters with this or
@@ -2301,7 +2276,6 @@
         String type = resolve ? intent.resolveType(resolver) : intent.getType();
         return match(intent.getAction(), type, intent.getScheme(),
                      intent.getData(), intent.getCategories(), logTag,
-                     CompatChanges.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS),
                      false /* supportWildcards */, null /* ignoreActions */,
                      intent.getExtras());
     }
@@ -2354,7 +2328,6 @@
             Uri data, Set<String> categories, String logTag, boolean supportWildcards,
             @Nullable Collection<String> ignoreActions) {
         return match(action, type, scheme, data, categories, logTag, supportWildcards,
-                CompatChanges.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS),
                 ignoreActions, null /* extras */);
     }
 
@@ -2366,10 +2339,8 @@
      */
     public final int match(String action, String type, String scheme,
             Uri data, Set<String> categories, String logTag, boolean supportWildcards,
-            boolean blockNullAction, @Nullable Collection<String> ignoreActions,
-            @Nullable Bundle extras) {
-        if ((action == null && blockNullAction)
-                || !matchAction(action, supportWildcards, ignoreActions)) {
+            @Nullable Collection<String> ignoreActions, @Nullable Bundle extras) {
+        if (action != null && !matchAction(action, supportWildcards, ignoreActions)) {
             if (false) Log.v(
                 logTag, "No matching action " + action + " for " + this);
             return NO_MATCH_ACTION;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a0c620a..9388823 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -5157,6 +5157,8 @@
      * Retrieve overall information about an application package that is
      * installed on the system.
      *
+     * Use {@link #getPackageInfo(String, PackageInfoFlags)} when long flags are needed.
+     *
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
      *            desired package.
      * @param flags Additional option flags to modify the data returned.
@@ -5169,9 +5171,7 @@
      *         deleted with {@code DELETE_KEEP_DATA} flag set).
      * @throws NameNotFoundException if no such package is available to the
      *             caller.
-     * @deprecated Use {@link #getPackageInfo(String, PackageInfoFlags)} instead.
      */
-    @Deprecated
     public abstract PackageInfo getPackageInfo(@NonNull String packageName, int flags)
             throws NameNotFoundException;
 
@@ -5195,6 +5195,8 @@
      * {@link #VERSION_CODE_HIGHEST} in the {@link VersionedPackage}
      * constructor.
      *
+     * Use {@link #getPackageInfo(VersionedPackage, PackageInfoFlags)} when long flags are needed.
+     *
      * @param versionedPackage The versioned package for which to query.
      * @param flags Additional option flags to modify the data returned.
      * @return A PackageInfo object containing information about the package. If
@@ -5206,9 +5208,7 @@
      *         deleted with {@code DELETE_KEEP_DATA} flag set).
      * @throws NameNotFoundException if no such package is available to the
      *             caller.
-     * @deprecated Use {@link #getPackageInfo(VersionedPackage, PackageInfoFlags)} instead.
      */
-    @Deprecated
     public abstract PackageInfo getPackageInfo(@NonNull VersionedPackage versionedPackage,
             int flags) throws NameNotFoundException;
 
@@ -5226,6 +5226,8 @@
      * Retrieve overall information about an application package that is
      * installed on the system.
      *
+     * Use {@link #getPackageInfoAsUser(String, PackageInfoFlags, int)} when long flags are needed.
+     *
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
      *            desired package.
      * @param flags Additional option flags to modify the data returned.
@@ -5239,10 +5241,8 @@
      *         deleted with {@code DELETE_KEEP_DATA} flag set).
      * @throws NameNotFoundException if no such package is available to the
      *             caller.
-     * @deprecated Use {@link #getPackageInfoAsUser(String, PackageInfoFlags, int)} instead.
      * @hide
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
     @UnsupportedAppUsage
@@ -5376,15 +5376,16 @@
      * Note that the same package may have different GIDs under different
      * {@link UserHandle} on the same device.
      *
+     * Use {@link #getPackageGids(String, PackageInfoFlags)} when long flags are needed.
+     *
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
      *            desired package.
      * @return Returns an int array of the assigned gids, or null if there are
      *         none.
      * @throws NameNotFoundException if no such package is available to the
      *             caller.
-     * @deprecated Use {@link #getPackageGids(String, PackageInfoFlags)} instead.
      */
-    @Deprecated
+
     public abstract int[] getPackageGids(@NonNull String packageName, int flags)
             throws NameNotFoundException;
 
@@ -5404,14 +5405,14 @@
      * Note that the same package will have different UIDs under different
      * {@link UserHandle} on the same device.
      *
+     * Use {@link #getPackageUid(String, PackageInfoFlags)} when long flags are needed.
+     *
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
      *            desired package.
      * @return Returns an integer UID who owns the given package name.
      * @throws NameNotFoundException if no such package is available to the
      *             caller.
-     * @deprecated Use {@link #getPackageUid(String, PackageInfoFlags)} instead.
      */
-    @Deprecated
     public abstract int getPackageUid(@NonNull String packageName, int flags)
             throws NameNotFoundException;
 
@@ -5445,10 +5446,9 @@
 
     /**
      * See {@link #getPackageUidAsUser(String, PackageInfoFlags, int)}.
-     * @deprecated Use {@link #getPackageUidAsUser(String, PackageInfoFlags, int)} instead.
+     * Use {@link #getPackageUidAsUser(String, PackageInfoFlags, int)} when long flags are needed.
      * @hide
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @UnsupportedAppUsage
     public abstract int getPackageUidAsUser(@NonNull String packageName,
@@ -5589,6 +5589,8 @@
      * Retrieve all of the information we know about a particular
      * package/application.
      *
+     * Use {@link #getApplicationInfo(String, ApplicationInfoFlags)} when long flags are needed.
+     *
      * @param packageName The full name (i.e. com.google.apps.contacts) of an
      *            application.
      * @param flags Additional option flags to modify the data returned.
@@ -5601,10 +5603,8 @@
      *         which had been deleted with {@code DELETE_KEEP_DATA} flag set).
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     * @deprecated Use {@link #getApplicationInfo(String, ApplicationInfoFlags)} instead.
      */
     @NonNull
-    @Deprecated
     public abstract ApplicationInfo getApplicationInfo(@NonNull String packageName,
             int flags) throws NameNotFoundException;
 
@@ -5619,13 +5619,13 @@
     }
 
     /**
-     * @deprecated Use {@link #getApplicationInfoAsUser(String, ApplicationInfoFlags, int)} instead.
+     * Use {@link #getApplicationInfoAsUser(String, ApplicationInfoFlags, int)} when long flags are
+     * needed.
      * {@hide}
      */
     @SuppressWarnings("HiddenAbstractMethod")
     @NonNull
     @UnsupportedAppUsage
-    @Deprecated
     public abstract ApplicationInfo getApplicationInfoAsUser(@NonNull String packageName,
             int flags, @UserIdInt int userId) throws NameNotFoundException;
 
@@ -5642,6 +5642,9 @@
      * Retrieve all of the information we know about a particular
      * package/application, for a specific user.
      *
+     * Use {@link #getApplicationInfoAsUser(String, ApplicationInfoFlags, UserHandle)} when long
+     * flags are needed.
+     *
      * @param packageName The full name (i.e. com.google.apps.contacts) of an
      *            application.
      * @param flags Additional option flags to modify the data returned.
@@ -5654,14 +5657,11 @@
      *         which had been deleted with {@code DELETE_KEEP_DATA} flag set).
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     * @deprecated Use {@link #getApplicationInfoAsUser(String, ApplicationInfoFlags, UserHandle)}
-     * instead.
      * @hide
      */
     @NonNull
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
     @SystemApi
-    @Deprecated
     public ApplicationInfo getApplicationInfoAsUser(@NonNull String packageName,
             int flags, @NonNull UserHandle user)
             throws NameNotFoundException {
@@ -5694,6 +5694,8 @@
      * Retrieve all of the information we know about a particular activity
      * class.
      *
+     * Use {@link #getActivityInfo(ComponentName, ComponentInfoFlags)} when long flags are needed.
+     *
      * @param component The full component name (i.e.
      *            com.google.apps.contacts/com.google.apps.contacts.
      *            ContactsList) of an Activity class.
@@ -5702,9 +5704,7 @@
      *         activity.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     * @deprecated Use {@link #getActivityInfo(ComponentName, ComponentInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract ActivityInfo getActivityInfo(@NonNull ComponentName component,
             int flags) throws NameNotFoundException;
@@ -5720,20 +5720,11 @@
     }
 
     /**
-     * @hide
-     */
-    @NonNull
-    public ActivityInfo getActivityInfoAsUser(@NonNull ComponentName component,
-            @NonNull ComponentInfoFlags flags, @UserIdInt int userId)
-            throws NameNotFoundException {
-        throw new UnsupportedOperationException(
-                "getActivityInfoAsUser not implemented in subclass");
-    }
-
-    /**
      * Retrieve all of the information we know about a particular receiver
      * class.
      *
+     * Use {@link #getReceiverInfo(ComponentName, ComponentInfoFlags)} when long flags are needed.
+     *
      * @param component The full component name (i.e.
      *            com.google.apps.calendar/com.google.apps.calendar.
      *            CalendarAlarm) of a Receiver class.
@@ -5742,9 +5733,7 @@
      *         receiver.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     * @deprecated Use {@link #getReceiverInfo(ComponentName, ComponentInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract ActivityInfo getReceiverInfo(@NonNull ComponentName component,
             int flags) throws NameNotFoundException;
@@ -5762,6 +5751,8 @@
     /**
      * Retrieve all of the information we know about a particular service class.
      *
+     * Use {@link #getServiceInfo(ComponentName, ComponentInfoFlags)} when long flags are needed.
+     *
      * @param component The full component name (i.e.
      *            com.google.apps.media/com.google.apps.media.
      *            BackgroundPlayback) of a Service class.
@@ -5769,9 +5760,7 @@
      * @return A {@link ServiceInfo} object containing information about the
      *         service.
      * @throws NameNotFoundException if the component cannot be found on the system.
-     * @deprecated Use {@link #getServiceInfo(ComponentName, ComponentInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract ServiceInfo getServiceInfo(@NonNull ComponentName component,
             int flags) throws NameNotFoundException;
@@ -5790,6 +5779,8 @@
      * Retrieve all of the information we know about a particular content
      * provider class.
      *
+     * Use {@link #getProviderInfo(ComponentName, ComponentInfoFlags)} when long flags are needed.
+     *
      * @param component The full component name (i.e.
      *            com.google.providers.media/com.google.providers.media.
      *            MediaProvider) of a ContentProvider class.
@@ -5798,9 +5789,7 @@
      *         provider.
      * @throws NameNotFoundException if a package with the given name cannot be
      *             found on the system.
-     * @deprecated Use {@link #getProviderInfo(ComponentName, ComponentInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract ProviderInfo getProviderInfo(@NonNull ComponentName component,
             int flags) throws NameNotFoundException;
@@ -5849,6 +5838,8 @@
     /**
      * Return a List of all packages that are installed for the current user.
      *
+     * Use {@link #getInstalledPackages(PackageInfoFlags)} when long flags are needed.
+     *
      * @param flags Additional option flags to modify the data returned.
      * @return A List of PackageInfo objects, one for each installed package,
      *         containing information about the package. In the unlikely case
@@ -5858,15 +5849,12 @@
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
      *         deleted with {@code DELETE_KEEP_DATA} flag set).
-     * @deprecated Use {@link #getInstalledPackages(PackageInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract List<PackageInfo> getInstalledPackages(int flags);
 
     /**
      * See {@link #getInstalledPackages(int)}.
-     * @param flags
      */
     @NonNull
     public List<PackageInfo> getInstalledPackages(@NonNull PackageInfoFlags flags) {
@@ -5896,6 +5884,9 @@
      * Return a List of all installed packages that are currently holding any of
      * the given permissions.
      *
+     * Use {@link #getPackagesHoldingPermissions(String[], PackageInfoFlags)} when long flags are
+     * needed.
+     *
      * @param flags Additional option flags to modify the data returned.
      * @return A List of PackageInfo objects, one for each installed package
      *         that holds any of the permissions that were provided, containing
@@ -5906,9 +5897,7 @@
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
      *         deleted with {@code DELETE_KEEP_DATA} flag set).
-     * @deprecated Use {@link #getPackagesHoldingPermissions(String[], PackageInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract List<PackageInfo> getPackagesHoldingPermissions(
             @NonNull String[] permissions, int flags);
@@ -5927,6 +5916,8 @@
      * Return a List of all packages that are installed on the device, for a
      * specific user.
      *
+     * Use {@link #getInstalledPackagesAsUser(PackageInfoFlags, int)} when long flags are needed.
+     *
      * @param flags Additional option flags to modify the data returned.
      * @param userId The user for whom the installed packages are to be listed
      * @return A List of PackageInfo objects, one for each installed package,
@@ -5937,10 +5928,8 @@
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
      *         deleted with {@code DELETE_KEEP_DATA} flag set).
-     * @deprecated Use {@link #getInstalledPackagesAsUser(PackageInfoFlags, int)} instead.
      * @hide
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @NonNull
     @SystemApi
@@ -6652,6 +6641,8 @@
      * applications including those deleted with {@code DELETE_KEEP_DATA}
      * (partially installed apps with data directory) will be returned.
      *
+     * Use {@link #getInstalledApplications(ApplicationInfoFlags)} when long flags are needed.
+     *
      * @param flags Additional option flags to modify the data returned.
      * @return A List of ApplicationInfo objects, one for each installed
      *         application. In the unlikely case there are no installed
@@ -6661,10 +6652,8 @@
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
      *         deleted with {@code DELETE_KEEP_DATA} flag set).
-     * @deprecated  Use {@link #getInstalledApplications(ApplicationInfoFlags)} instead.
      */
     @NonNull
-    @Deprecated
     public abstract List<ApplicationInfo> getInstalledApplications(int flags);
 
     /**
@@ -6683,6 +6672,9 @@
      * {@code DELETE_KEEP_DATA} (partially installed apps with data directory)
      * will be returned.
      *
+     * Use {@link #getInstalledApplicationsAsUser(ApplicationInfoFlags, int)} when long flags are
+     * needed.
+     *
      * @param flags Additional option flags to modify the data returned.
      * @param userId The user for whom the installed applications are to be
      *            listed
@@ -6694,13 +6686,11 @@
      *         applications (which includes installed applications as well as
      *         applications with data directory i.e. applications which had been
      *         deleted with {@code DELETE_KEEP_DATA} flag set).
-     * @deprecated  Use {@link #getInstalledApplicationsAsUser(ApplicationInfoFlags, int)} instead.
      * @hide
      */
     @SuppressWarnings("HiddenAbstractMethod")
     @NonNull
     @TestApi
-    @Deprecated
     public abstract List<ApplicationInfo> getInstalledApplicationsAsUser(
             int flags, @UserIdInt int userId);
 
@@ -6859,13 +6849,13 @@
     /**
      * Get a list of shared libraries on the device.
      *
+     * Use {@link #getSharedLibraries(PackageInfoFlags)} when long flags are needed.
+     *
      * @param flags To filter the libraries to return.
      * @return The shared library list.
      *
      * @see #MATCH_UNINSTALLED_PACKAGES
-     * @deprecated Use {@link #getSharedLibraries(PackageInfoFlags)} instead.
      */
-    @Deprecated
     public abstract @NonNull List<SharedLibraryInfo> getSharedLibraries(int flags);
 
     /**
@@ -6880,6 +6870,8 @@
     /**
      * Get a list of shared libraries on the device.
      *
+     * Use {@link #getSharedLibrariesAsUser(PackageInfoFlags, int)} when long flags are needed.
+     *
      * @param flags To filter the libraries to return.
      * @param userId The user to query for.
      * @return The shared library list.
@@ -6890,9 +6882,7 @@
      * @see #MATCH_UNINSTALLED_PACKAGES
      *
      * @hide
-     * @deprecated Use {@link #getSharedLibrariesAsUser(PackageInfoFlags, int)} instead.
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     public abstract @NonNull List<SharedLibraryInfo> getSharedLibrariesAsUser(int flags,
             @UserIdInt int userId);
@@ -6910,14 +6900,14 @@
     /**
      * Get the list of shared libraries declared by a package.
      *
+     * Use {@link #getDeclaredSharedLibraries(String, PackageInfoFlags)} when long flags are needed.
+     *
      * @param packageName the package name to query
      * @param flags the flags to filter packages
      * @return the shared library list
      *
      * @hide
-     * @deprecated Use {@link #getDeclaredSharedLibraries(String, PackageInfoFlags)} instead.
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @NonNull
     @RequiresPermission(Manifest.permission.ACCESS_SHARED_LIBRARIES)
@@ -7026,6 +7016,8 @@
      * Intent.resolveActivity(PackageManager)} do.
      * </p>
      *
+     * Use {@link #resolveActivity(Intent, ResolveInfoFlags)} when long flags are needed.
+     *
      * @param intent An intent containing all of the desired specification
      *            (action, data, type, category, and/or component).
      * @param flags Additional option flags to modify the data returned. The
@@ -7037,9 +7029,7 @@
      *         matching activity was found. If multiple matching activities are
      *         found and there is no default set, returns a ResolveInfo object
      *         containing something else, such as the activity resolver.
-     * @deprecated Use {@link #resolveActivity(Intent, ResolveInfoFlags)} instead.
      */
-    @Deprecated
     @Nullable
     public abstract ResolveInfo resolveActivity(@NonNull Intent intent, int flags);
 
@@ -7066,6 +7056,8 @@
      * Intent.resolveActivity(PackageManager)} do.
      * </p>
      *
+     * Use {@link #resolveActivityAsUser(Intent, ResolveInfoFlags, int)} when long flags are needed.
+     *
      * @param intent An intent containing all of the desired specification
      *            (action, data, type, category, and/or component).
      * @param flags Additional option flags to modify the data returned. The
@@ -7079,9 +7071,7 @@
      *         found and there is no default set, returns a ResolveInfo object
      *         containing something else, such as the activity resolver.
      * @hide
-     * @deprecated Use {@link #resolveActivityAsUser(Intent, ResolveInfoFlags, int)} instead.
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @Nullable
     @UnsupportedAppUsage
@@ -7102,6 +7092,8 @@
     /**
      * Retrieve all activities that can be performed for the given intent.
      *
+     * Use {@link #queryIntentActivities(Intent, ResolveInfoFlags)} when long flags are needed.
+     *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags to modify the data returned. The
      *            most important is {@link #MATCH_DEFAULT_ONLY}, to limit the
@@ -7113,9 +7105,7 @@
      *         words, the first item is what would be returned by
      *         {@link #resolveActivity}. If there are no matching activities, an
      *         empty list is returned.
-     * @deprecated Use {@link #queryIntentActivities(Intent, ResolveInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract List<ResolveInfo> queryIntentActivities(@NonNull Intent intent, int flags);
 
@@ -7133,6 +7123,9 @@
      * Retrieve all activities that can be performed for the given intent, for a
      * specific user.
      *
+     * Use {@link #queryIntentActivitiesAsUser(Intent, ResolveInfoFlags, int)} when long flags are
+     * needed.
+     *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags to modify the data returned. The
      *            most important is {@link #MATCH_DEFAULT_ONLY}, to limit the
@@ -7145,9 +7138,7 @@
      *         {@link #resolveActivity}. If there are no matching activities, an
      *         empty list is returned.
      * @hide
-     * @deprecated Use {@link #queryIntentActivitiesAsUser(Intent, ResolveInfoFlags, int)} instead.
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @NonNull
     @UnsupportedAppUsage
@@ -7169,6 +7160,9 @@
      * Retrieve all activities that can be performed for the given intent, for a
      * specific user.
      *
+     * Use {@link #queryIntentActivitiesAsUser(Intent, ResolveInfoFlags, UserHandle)} when long
+     * flags are needed.
+     *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags to modify the data returned. The
      *            most important is {@link #MATCH_DEFAULT_ONLY}, to limit the
@@ -7182,10 +7176,7 @@
      *         {@link #resolveActivity}. If there are no matching activities, an
      *         empty list is returned.
      * @hide
-     * @deprecated Use {@link #queryIntentActivitiesAsUser(Intent, ResolveInfoFlags, UserHandle)}
-     * instead.
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @NonNull
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
@@ -7215,6 +7206,9 @@
      * final ResolveInfo list in a reasonable order, with no duplicates, based
      * on those inputs.
      *
+     * Use {@link #queryIntentActivityOptions(ComponentName, List, Intent, ResolveInfoFlags)} when
+     * long flags are needed.
+     *
      * @param caller The class name of the activity that is making the request.
      *            This activity will never appear in the output list. Can be
      *            null.
@@ -7231,10 +7225,7 @@
      *         activities that can handle <var>intent</var> but did not get
      *         included by one of the <var>specifics</var> intents. If there are
      *         no matching activities, an empty list is returned.
-     * @deprecated Use {@link #queryIntentActivityOptions(ComponentName, List, Intent,
-     * ResolveInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract List<ResolveInfo> queryIntentActivityOptions(@Nullable ComponentName caller,
             @Nullable Intent[] specifics, @NonNull Intent intent, int flags);
@@ -7253,14 +7244,14 @@
     /**
      * Retrieve all receivers that can handle a broadcast of the given intent.
      *
+     * Use {@link #queryBroadcastReceivers(Intent, ResolveInfoFlags)} when long flags are needed.
+     *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags to modify the data returned.
      * @return Returns a List of ResolveInfo objects containing one entry for
      *         each matching receiver, ordered from best to worst. If there are
      *         no matching receivers, an empty list or null is returned.
-     * @deprecated Use {@link #queryBroadcastReceivers(Intent, ResolveInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract List<ResolveInfo> queryBroadcastReceivers(@NonNull Intent intent, int flags);
 
@@ -7278,6 +7269,9 @@
      * Retrieve all receivers that can handle a broadcast of the given intent,
      * for a specific user.
      *
+     * Use {@link #queryBroadcastReceiversAsUser(Intent, ResolveInfoFlags, UserHandle)} when long
+     * flags are needed.
+     *
      * @param intent The desired intent as per resolveActivity().
      * @param flags Additional option flags to modify the data returned.
      * @param userHandle UserHandle of the user being queried.
@@ -7285,10 +7279,7 @@
      *         each matching receiver, ordered from best to worst. If there are
      *         no matching receivers, an empty list or null is returned.
      * @hide
-     * @deprecated Use {@link #queryBroadcastReceiversAsUser(Intent, ResolveInfoFlags, UserHandle)}
-     * instead.
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @NonNull
     @SystemApi
@@ -7312,10 +7303,9 @@
 
     /**
      * @hide
-     * @deprecated Use {@link #queryBroadcastReceiversAsUser(Intent, ResolveInfoFlags, int)}
-     * instead.
+     * Use {@link #queryBroadcastReceiversAsUser(Intent, ResolveInfoFlags, int)} when long flags are
+     * needed.
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @NonNull
     @UnsupportedAppUsage
@@ -7353,15 +7343,15 @@
     /**
      * Determine the best service to handle for a given Intent.
      *
+     * Use {@link #resolveService(Intent, ResolveInfoFlags)} when long flags are needed.
+     *
      * @param intent An intent containing all of the desired specification
      *            (action, data, type, category, and/or component).
      * @param flags Additional option flags to modify the data returned.
      * @return Returns a ResolveInfo object containing the final service intent
      *         that was determined to be the best action. Returns null if no
      *         matching service was found.
-     * @deprecated Use {@link #resolveService(Intent, ResolveInfoFlags)} instead.
      */
-    @Deprecated
     @Nullable
     public abstract ResolveInfo resolveService(@NonNull Intent intent, int flags);
 
@@ -7376,9 +7366,8 @@
 
     /**
      * @hide
-     * @deprecated Use {@link #resolveServiceAsUser(Intent, ResolveInfoFlags, int)} instead.
+     * Use {@link #resolveServiceAsUser(Intent, ResolveInfoFlags, int)} when long flags are needed.
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @Nullable
     public abstract ResolveInfo resolveServiceAsUser(@NonNull Intent intent,
@@ -7398,6 +7387,8 @@
     /**
      * Retrieve all services that can match the given intent.
      *
+     * Use {@link #queryIntentServices(Intent, ResolveInfoFlags)} when long flags are needed.
+     *
      * @param intent The desired intent as per resolveService().
      * @param flags Additional option flags to modify the data returned.
      * @return Returns a List of ResolveInfo objects containing one entry for
@@ -7405,9 +7396,7 @@
      *         words, the first item is what would be returned by
      *         {@link #resolveService}. If there are no matching services, an
      *         empty list or null is returned.
-     * @deprecated Use {@link #queryIntentServices(Intent, ResolveInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract List<ResolveInfo> queryIntentServices(@NonNull Intent intent,
             int flags);
@@ -7425,6 +7414,9 @@
     /**
      * Retrieve all services that can match the given intent for a given user.
      *
+     * Use {@link #queryIntentServicesAsUser(Intent, ResolveInfoFlags, int)} when long flags are
+     * needed.
+     *
      * @param intent The desired intent as per resolveService().
      * @param flags Additional option flags to modify the data returned.
      * @param userId The user id.
@@ -7434,9 +7426,7 @@
      *         {@link #resolveService}. If there are no matching services, an
      *         empty list or null is returned.
      * @hide
-     * @deprecated Use {@link #queryIntentServicesAsUser(Intent, ResolveInfoFlags, int)} instead.
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @NonNull
     @UnsupportedAppUsage
@@ -7457,6 +7447,9 @@
     /**
      * Retrieve all services that can match the given intent for a given user.
      *
+     * Use {@link #queryIntentServicesAsUser(Intent, ResolveInfoFlags, UserHandle)} when long flags
+     * are needed.
+     *
      * @param intent The desired intent as per resolveService().
      * @param flags Additional option flags to modify the data returned.
      * @param user The user being queried.
@@ -7466,10 +7459,7 @@
      *         {@link #resolveService}. If there are no matching services, an
      *         empty list or null is returned.
      * @hide
-     * @deprecated Use {@link #queryIntentServicesAsUser(Intent, ResolveInfoFlags, UserHandle)}
-     * instead.
      */
-    @Deprecated
     @NonNull
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
     @SystemApi
@@ -7492,6 +7482,9 @@
     /**
      * Retrieve all providers that can match the given intent.
      *
+     * Use {@link #queryIntentContentProvidersAsUser(Intent, ResolveInfoFlags, int)} when long flags
+     * are needed.
+     *
      * @param intent An intent containing all of the desired specification
      *            (action, data, type, category, and/or component).
      * @param flags Additional option flags to modify the data returned.
@@ -7500,10 +7493,7 @@
      *         each matching provider, ordered from best to worst. If there are
      *         no matching services, an empty list or null is returned.
      * @hide
-     * @deprecated Use {@link #queryIntentContentProvidersAsUser(Intent, ResolveInfoFlags, int)}
-     * instead.
      */
-    @Deprecated
     @SuppressWarnings("HiddenAbstractMethod")
     @NonNull
     @UnsupportedAppUsage
@@ -7524,6 +7514,9 @@
     /**
      * Retrieve all providers that can match the given intent.
      *
+     * Use {@link #queryIntentContentProvidersAsUser(Intent, ResolveInfoFlags, UserHandle)} when
+     * long flags are needed.
+     *
      * @param intent An intent containing all of the desired specification
      *            (action, data, type, category, and/or component).
      * @param flags Additional option flags to modify the data returned.
@@ -7532,10 +7525,7 @@
      *         each matching provider, ordered from best to worst. If there are
      *         no matching services, an empty list or null is returned.
      * @hide
-     * @deprecated Use {@link #queryIntentContentProvidersAsUser(Intent, ResolveInfoFlags,
-     * UserHandle)} instead.
      */
-    @Deprecated
     @NonNull
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
     @SystemApi
@@ -7559,15 +7549,16 @@
     /**
      * Retrieve all providers that can match the given intent.
      *
+     * Use {@link #queryIntentContentProviders(Intent, ResolveInfoFlags)} when long flags are
+     * needed.
+     *
      * @param intent An intent containing all of the desired specification
      *            (action, data, type, category, and/or component).
      * @param flags Additional option flags to modify the data returned.
      * @return Returns a List of ResolveInfo objects containing one entry for
      *         each matching provider, ordered from best to worst. If there are
      *         no matching services, an empty list or null is returned.
-     * @deprecated Use {@link #queryIntentContentProviders(Intent, ResolveInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract List<ResolveInfo> queryIntentContentProviders(@NonNull Intent intent,
             int flags);
@@ -7591,13 +7582,13 @@
      * ProviderInfo info = packageManager.resolveContentProvider(uri.getAuthority(), flags);
      * </pre>
      *
+     * Use {@link #resolveContentProvider(String, ComponentInfoFlags)} when long flags are needed.
+     *
      * @param authority The authority of the provider to find.
      * @param flags Additional option flags to modify the data returned.
      * @return A {@link ProviderInfo} object containing information about the
      *         provider. If a provider was not found, returns null.
-     * @deprecated Use {@link #resolveContentProvider(String, ComponentInfoFlags)} instead.
      */
-    @Deprecated
     @Nullable
     public abstract ProviderInfo resolveContentProvider(@NonNull String authority,
             int flags);
@@ -7615,14 +7606,15 @@
     /**
      * Find a single content provider by its base path name.
      *
+     * Use {@link #resolveContentProviderAsUser(String, ComponentInfoFlags, int)} when long flags
+     * are needed.
+     *
      * @param providerName The name of the provider to find.
      * @param flags Additional option flags to modify the data returned.
      * @param userId The user id.
      * @return A {@link ProviderInfo} object containing information about the
      *         provider. If a provider was not found, returns null.
      * @hide
-     * @deprecated Use {@link #resolveContentProviderAsUser(String, ComponentInfoFlags, int)}
-     * instead.
      */
     @SuppressWarnings("HiddenAbstractMethod")
     @Nullable
@@ -7647,6 +7639,9 @@
      * <em>Note: unlike most other methods, an empty result set is indicated
      * by a null return instead of an empty list.</em>
      *
+     * Use {@link #queryContentProviders(String, int, ComponentInfoFlags)} when long flags are
+     * needed.
+     *
      * @param processName If non-null, limits the returned providers to only
      *            those that are hosted by the given process. If null, all
      *            content providers are returned.
@@ -7657,9 +7652,7 @@
      *         each provider either matching <var>processName</var> or, if
      *         <var>processName</var> is null, all known content providers.
      *         <em>If there are no matching providers, null is returned.</em>
-     * @deprecated Use {@link #queryContentProviders(String, int, ComponentInfoFlags)} instead.
      */
-    @Deprecated
     @NonNull
     public abstract List<ProviderInfo> queryContentProviders(
             @Nullable String processName, int uid, int flags);
@@ -7687,11 +7680,11 @@
      * to mark GAL providers, rather than intent filters, so we can't use
      * {@link #queryIntentContentProviders} for that.
      *
+     * Use {@link #queryContentProviders(String, int, ComponentInfoFlags, String)} when long flags
+     * are needed.
+     *
      * @hide
-     * @deprecated Use {@link #queryContentProviders(String, int, ComponentInfoFlags, String)}
-     * instead.
      */
-    @Deprecated
     @NonNull
     public List<ProviderInfo> queryContentProviders(@Nullable String processName,
             int uid, int flags, String metaDataKey) {
@@ -8237,13 +8230,13 @@
      * Retrieve overall information about an application package defined in a
      * package archive file
      *
+     * Use {@link #getPackageArchiveInfo(String, PackageInfoFlags)} when long flags are needed.
+     *
      * @param archiveFilePath The path to the archive file
      * @param flags Additional option flags to modify the data returned.
      * @return A PackageInfo object containing information about the package
      *         archive. If the package could not be parsed, returns null.
-     * @deprecated Use {@link #getPackageArchiveInfo(String, PackageInfoFlags)} instead.
      */
-    @Deprecated
     @Nullable
     public PackageInfo getPackageArchiveInfo(@NonNull String archiveFilePath, int flags) {
         return getPackageArchiveInfo(archiveFilePath, PackageInfoFlags.of(flags));
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 02b9308..1a3c3d9 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -376,8 +376,8 @@
      *   <li>Headless system apps</li>
      *   <li><a href="{@docRoot}guide/topics/admin/device-admin">Device admin apps</a></li>
      *   <li>Active VPN apps</li>
-     *   <li>Apps holding {@link Manifest.permission#SCHEDULE_EXACT_ALARM} or
-     *       {@link Manifest.permission#USE_EXACT_ALARM} permission.</li>
+     *   <li>Apps holding {@link android.Manifest.permission#SCHEDULE_EXACT_ALARM} or
+     *       {@link android.Manifest.permission#USE_EXACT_ALARM} permission.</li>
      * </ul>
      * </p>
      */
@@ -393,7 +393,7 @@
      *
      * <p>Unlike other foreground service types, this type is not associated with a specific use
      * case, and it will not require any special permissions
-     * (besides {@link Manifest.permission#FOREGROUND_SERVICE}).
+     * (besides {@link android.Manifest.permission#FOREGROUND_SERVICE}).
      *
      * However, this type has the following restrictions.
      *
@@ -401,19 +401,21 @@
      *     <li>
      *         The type has a 3 minute timeout.
      *         A foreground service of this type must be stopped within the timeout by
-     *         {@link android.app.Service#stopSelf),
-     *         or {@link android.content.Context#stopService).
-     *         {@link android.app.Service#stopForeground) will also work, which will demote the
+     *         {@link android.app.Service#stopSelf()},
+     *         {@link android.content.Context#stopService(android.content.Intent)}
+     *         or their overloads).
+     *         {@link android.app.Service#stopForeground(int)} will also work,
+     *         which will demote the
      *         service to a "background" service, which will soon be stopped by the system.
      *
-     *         <p>The system will <em>not</em> automatically stop it.
-     *
      *         <p>If the service isn't stopped within the timeout,
-     *         {@link android.app.Service#onTimeout(int)} will be called.
+     *         {@link android.app.Service#onTimeout(int)} will be called. Note, even when the
+     *         system calls this callback, it will not stop the service automatically.
+     *         You still need to stop the service using one of the aforementioned
+     *         ways even when you get this callback.
      *
      *         <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.
-     *
+     *         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"
      *         (see {@link android.app.Service#START_STICKY}). That is, if an app is killed
@@ -427,10 +429,26 @@
      *         <a href="/guide/components/foreground-services#background-start-restrictions>
      *             Restrictions on background starts
      *         </a>
+     *     <li>
+     *         You can combine multiple foreground services types with {@code |}s, and you can
+     *         combine
+     *         {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}.
+     *         with other types as well.
+     *         However,
+     *         {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}
+     *         is for situations
+     *         where you have no other valid foreground services to use and the timeout is long
+     *         enough for the task, and if you can use other types, there's no point using
+     *         this type.
+     *         For this reason, if
+     *         {@link android.content.pm.ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}
+     *         is combined with other foreground service types, the system will simply ignore
+     *         it, and as a result,
+     *         none of the above restrictions will apply (e.g. there'll be no timeout).
      * </ul>
      *
-     * <p>Note, even though
-     * {@link ServiceInfo#FOREGROUND_SERVICE_TYPE_SHORT_SERVICE}
+     * <p>Also note, even though
+     * {@link android.content.pm.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
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index 45e0efb..f440ac7 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -29,6 +29,9 @@
     },
     {
       "path": "system/apex/tests"
+    },
+    {
+      "path": "cts/tests/tests/content/pm/SecureFrp"
     }
   ],
   "presubmit": [
@@ -141,17 +144,6 @@
       ]
     },
     {
-      "name": "CtsSecureFrpInstallTestCases",
-      "options": [
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        },
-        {
-          "exclude-annotation": "org.junit.Ignore"
-        }
-      ]
-    },
-    {
       "name": "CtsSuspendAppsPermissionTestCases",
       "options": [
         {
diff --git a/core/java/android/content/pm/UserPackage.java b/core/java/android/content/pm/UserPackage.java
index 7ca92c3..c35e678 100644
--- a/core/java/android/content/pm/UserPackage.java
+++ b/core/java/android/content/pm/UserPackage.java
@@ -18,14 +18,16 @@
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
-import android.os.Process;
-import android.os.UserHandle;
 import android.util.SparseArrayMap;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 
+import libcore.util.EmptyArray;
+
 import java.util.Objects;
+import java.util.Random;
 
 /**
  * POJO to represent a package for a specific user ID.
@@ -34,6 +36,16 @@
  */
 public final class UserPackage {
     private static final boolean ENABLE_CACHING = true;
+    /**
+     * The maximum number of entries to keep in the cache per user ID.
+     * The value should ideally be high enough to cover all packages on an end-user device,
+     * but low enough that stale or invalid packages would eventually (probably) get removed.
+     * This should benefit components that loop through all packages on a device and use this class,
+     * since being able to cache the objects for all packages on the device
+     * means we don't have to keep recreating the objects.
+     */
+    @VisibleForTesting
+    static final int MAX_NUM_CACHED_ENTRIES_PER_USER = 1000;
 
     @UserIdInt
     public final int userId;
@@ -43,11 +55,13 @@
     @GuardedBy("sCacheLock")
     private static final SparseArrayMap<String, UserPackage> sCache = new SparseArrayMap<>();
 
-    private static final class NoPreloadHolder {
-        /** Set of userIDs to cache objects for. */
-        @GuardedBy("sCacheLock")
-        private static int[] sUserIds = new int[]{UserHandle.getUserId(Process.myUid())};
-    }
+    /**
+     * Set of userIDs to cache objects for. We start off with an empty set, so there's no caching
+     * by default. The system will override with a valid set of userIDs in its process so that
+     * caching becomes active in the system process.
+     */
+    @GuardedBy("sCacheLock")
+    private static int[] sUserIds = EmptyArray.INT;
 
     private UserPackage(int userId, String packageName) {
         this.userId = userId;
@@ -87,13 +101,14 @@
         }
 
         synchronized (sCacheLock) {
-            if (!ArrayUtils.contains(NoPreloadHolder.sUserIds, userId)) {
+            if (!ArrayUtils.contains(sUserIds, userId)) {
                 // Don't cache objects for invalid userIds.
                 return new UserPackage(userId, packageName);
             }
 
             UserPackage up = sCache.get(userId, packageName);
             if (up == null) {
+                maybePurgeRandomEntriesLocked(userId);
                 packageName = packageName.intern();
                 up = new UserPackage(userId, packageName);
                 sCache.add(userId, packageName, up);
@@ -121,7 +136,7 @@
 
         userIds = userIds.clone();
         synchronized (sCacheLock) {
-            NoPreloadHolder.sUserIds = userIds;
+            sUserIds = userIds;
 
             for (int u = sCache.numMaps() - 1; u >= 0; --u) {
                 final int userId = sCache.keyAt(u);
@@ -131,4 +146,35 @@
             }
         }
     }
+
+    @VisibleForTesting
+    public static int numEntriesForUser(int userId) {
+        synchronized (sCacheLock) {
+            return sCache.numElementsForKey(userId);
+        }
+    }
+
+    /** Purge a random set of entries if the cache size is too large. */
+    @GuardedBy("sCacheLock")
+    private static void maybePurgeRandomEntriesLocked(int userId) {
+        final int uIdx = sCache.indexOfKey(userId);
+        if (uIdx < 0) {
+            return;
+        }
+        int numCached = sCache.numElementsForKeyAt(uIdx);
+        if (numCached < MAX_NUM_CACHED_ENTRIES_PER_USER) {
+            return;
+        }
+        // Purge a random set of 1% of cached elements for the userId. We don't want to use a
+        // deterministic system of purging because that may cause us to repeatedly remove elements
+        // that are frequently added and queried more than others. Choosing a random set
+        // means we will probably eventually remove less useful elements.
+        // An LRU cache is too expensive for this commonly used utility class.
+        final Random rand = new Random();
+        final int numToPurge = Math.max(1, MAX_NUM_CACHED_ENTRIES_PER_USER / 100);
+        for (int i = 0; i < numToPurge && numCached > 0; ++i) {
+            final int removeIdx = rand.nextInt(numCached--);
+            sCache.deleteAt(uIdx, removeIdx);
+        }
+    }
 }
diff --git a/core/java/android/content/res/FontScaleConverterFactory.java b/core/java/android/content/res/FontScaleConverterFactory.java
index ffdc7b38..6b09c30 100644
--- a/core/java/android/content/res/FontScaleConverterFactory.java
+++ b/core/java/android/content/res/FontScaleConverterFactory.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.util.MathUtils;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -98,22 +99,81 @@
     public static FontScaleConverter forScale(float fontScale) {
         if (fontScale <= 1) {
             // We don't need non-linear curves for shrinking text or for 100%.
-            // Also, fontScale==0 should not have a curve either
+            // Also, fontScale==0 should not have a curve either.
+            // And ignore negative font scales; that's just silly.
             return null;
         }
 
         FontScaleConverter lookupTable = get(fontScale);
-        // TODO(b/247861716): interpolate between two tables when null
+        if (lookupTable != null) {
+            return lookupTable;
+        }
 
-        return lookupTable;
+        // Didn't find an exact match: interpolate between two existing tables
+        final int index = LOOKUP_TABLES.indexOfKey(getKey(fontScale));
+        if (index >= 0) {
+            // This should never happen, should have been covered by get() above.
+            return LOOKUP_TABLES.valueAt(index);
+        }
+        // Didn't find an exact match: interpolate between two existing tables
+        final int lowerIndex = -(index + 1) - 1;
+        final int higherIndex = lowerIndex + 1;
+        if (lowerIndex < 0 || higherIndex >= LOOKUP_TABLES.size()) {
+            // We have gone beyond our bounds and have nothing to interpolate between. Just give
+            // them a straight linear table instead.
+            // This works because when FontScaleConverter encounters a size beyond its bounds, it
+            // calculates a linear fontScale factor using the ratio of the last element pair.
+            return new FontScaleConverter(new float[] {1f}, new float[] {fontScale});
+        } else {
+            float startScale = getScaleFromKey(LOOKUP_TABLES.keyAt(lowerIndex));
+            float endScale = getScaleFromKey(LOOKUP_TABLES.keyAt(higherIndex));
+            float interpolationPoint = MathUtils.constrainedMap(
+                    /* rangeMin= */ 0f,
+                    /* rangeMax= */ 1f,
+                    startScale,
+                    endScale,
+                    fontScale
+            );
+            return createInterpolatedTableBetween(
+                    LOOKUP_TABLES.valueAt(lowerIndex),
+                    LOOKUP_TABLES.valueAt(higherIndex),
+                    interpolationPoint);
+        }
+    }
+
+    @NonNull
+    private static FontScaleConverter createInterpolatedTableBetween(
+            FontScaleConverter start,
+            FontScaleConverter end,
+            float interpolationPoint
+    ) {
+        float[] commonSpSizes = new float[] { 8f, 10f, 12f, 14f, 18f, 20f, 24f, 30f, 100f};
+        float[] dpInterpolated = new float[commonSpSizes.length];
+
+        for (int i = 0; i < commonSpSizes.length; i++) {
+            float sp = commonSpSizes[i];
+            float startDp = start.convertSpToDp(sp);
+            float endDp = end.convertSpToDp(sp);
+            dpInterpolated[i] = MathUtils.lerp(startDp, endDp, interpolationPoint);
+        }
+
+        return new FontScaleConverter(commonSpSizes, dpInterpolated);
+    }
+
+    private static int getKey(float fontScale) {
+        return (int) (fontScale * SCALE_KEY_MULTIPLIER);
+    }
+
+    private static float getScaleFromKey(int key) {
+        return (float) key / SCALE_KEY_MULTIPLIER;
     }
 
     private static void put(float scaleKey, @NonNull FontScaleConverter fontScaleConverter) {
-        LOOKUP_TABLES.put((int) (scaleKey * SCALE_KEY_MULTIPLIER), fontScaleConverter);
+        LOOKUP_TABLES.put(getKey(scaleKey), fontScaleConverter);
     }
 
     @Nullable
     private static FontScaleConverter get(float scaleKey) {
-        return LOOKUP_TABLES.get((int) (scaleKey * SCALE_KEY_MULTIPLIER));
+        return LOOKUP_TABLES.get(getKey(scaleKey));
     }
 }
diff --git a/core/java/android/content/res/OWNERS b/core/java/android/content/res/OWNERS
index d12d920..a7bce12 100644
--- a/core/java/android/content/res/OWNERS
+++ b/core/java/android/content/res/OWNERS
@@ -4,3 +4,5 @@
 toddke@google.com
 patb@google.com
 zyy@google.com
+
+per-file FontScaleConverter*=fuego@google.com
\ No newline at end of file
diff --git a/core/java/android/credentials/CreateCredentialRequest.java b/core/java/android/credentials/CreateCredentialRequest.java
index b756a43..c89a5c6 100644
--- a/core/java/android/credentials/CreateCredentialRequest.java
+++ b/core/java/android/credentials/CreateCredentialRequest.java
@@ -244,7 +244,7 @@
     /** A builder for {@link CreateCredentialRequest}. */
     public static final class Builder {
 
-        private boolean mAlwaysSendAppInfoToProvider;
+        private boolean mAlwaysSendAppInfoToProvider = true;
 
         @NonNull
         private String mType;
diff --git a/core/java/android/credentials/ui/CancelUiRequest.java b/core/java/android/credentials/ui/CancelUiRequest.java
new file mode 100644
index 0000000..6bd9de4
--- /dev/null
+++ b/core/java/android/credentials/ui/CancelUiRequest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 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.credentials.ui;
+
+import android.annotation.NonNull;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.AnnotationValidations;
+
+/**
+ * A request to cancel any ongoing UI matching this request.
+ *
+ * @hide
+ */
+public final class CancelUiRequest implements Parcelable {
+
+    /**
+     * The intent extra key for the {@code CancelUiRequest} object when launching the UX
+     * activities.
+     */
+    @NonNull public static final String EXTRA_CANCEL_UI_REQUEST =
+            "android.credentials.ui.extra.EXTRA_CANCEL_UI_REQUEST";
+
+    @NonNull
+    private final IBinder mToken;
+
+    /** Returns the request token matching the user request that should be cancelled. */
+    @NonNull
+    public IBinder getToken() {
+        return mToken;
+    }
+
+    public CancelUiRequest(@NonNull IBinder token) {
+        mToken = token;
+    }
+
+    private CancelUiRequest(@NonNull Parcel in) {
+        mToken = in.readStrongBinder();
+        AnnotationValidations.validate(NonNull.class, null, mToken);
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeStrongBinder(mToken);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull public static final Creator<CancelUiRequest> CREATOR = new Creator<>() {
+        @Override
+        public CancelUiRequest createFromParcel(@NonNull Parcel in) {
+            return new CancelUiRequest(in);
+        }
+
+        @Override
+        public CancelUiRequest[] newArray(int size) {
+            return new CancelUiRequest[size];
+        }
+    };
+}
diff --git a/core/java/android/credentials/ui/IntentFactory.java b/core/java/android/credentials/ui/IntentFactory.java
index 3c10e81..dcfef56 100644
--- a/core/java/android/credentials/ui/IntentFactory.java
+++ b/core/java/android/credentials/ui/IntentFactory.java
@@ -22,6 +22,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.res.Resources;
+import android.os.IBinder;
 import android.os.Parcel;
 import android.os.ResultReceiver;
 
@@ -66,6 +67,25 @@
     }
 
     /**
+     * Creates an Intent that cancels any UI matching the given request token id.
+     *
+     * @hide
+     */
+    @NonNull
+    public static Intent createCancelUiIntent(@NonNull IBinder requestToken) {
+        Intent intent = new Intent();
+        ComponentName componentName =
+                ComponentName.unflattenFromString(
+                        Resources.getSystem()
+                                .getString(
+                                        com.android.internal.R.string
+                                                .config_credentialManagerDialogComponent));
+        intent.setComponent(componentName);
+        intent.putExtra(CancelUiRequest.EXTRA_CANCEL_UI_REQUEST, new CancelUiRequest(requestToken));
+        return intent;
+    }
+
+    /**
      * Notify the UI that providers have been enabled/disabled.
      *
      * @hide
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 9388ae3..73157e6 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -17,10 +17,10 @@
 package android.hardware;
 
 import static android.companion.virtual.VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
 import static android.companion.virtual.VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
+import static android.content.Context.DEVICE_ID_DEFAULT;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 import android.companion.virtual.VirtualDeviceManager;
@@ -92,7 +92,8 @@
     private static native boolean nativeIsDataInjectionEnabled(long nativeInstance);
 
     private static native int nativeCreateDirectChannel(
-            long nativeInstance, long size, int channelType, int fd, HardwareBuffer buffer);
+            long nativeInstance, int deviceId, long size, int channelType, int fd,
+            HardwareBuffer buffer);
     private static native void nativeDestroyDirectChannel(
             long nativeInstance, int channelHandle);
     private static native int nativeConfigDirectChannel(
@@ -695,6 +696,10 @@
     /** @hide */
     protected SensorDirectChannel createDirectChannelImpl(
             MemoryFile memoryFile, HardwareBuffer hardwareBuffer) {
+        int deviceId = mContext.getDeviceId();
+        if (isDeviceSensorPolicyDefault(deviceId)) {
+            deviceId = DEVICE_ID_DEFAULT;
+        }
         int id;
         int type;
         long size;
@@ -713,8 +718,8 @@
             }
 
             size = memoryFile.length();
-            id = nativeCreateDirectChannel(
-                    mNativeInstance, size, SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
+            id = nativeCreateDirectChannel(mNativeInstance, deviceId, size,
+                    SensorDirectChannel.TYPE_MEMORY_FILE, fd, null);
             if (id <= 0) {
                 throw new UncheckedIOException(
                         new IOException("create MemoryFile direct channel failed " + id));
@@ -738,7 +743,7 @@
             }
             size = hardwareBuffer.getWidth();
             id = nativeCreateDirectChannel(
-                    mNativeInstance, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
+                    mNativeInstance, deviceId, size, SensorDirectChannel.TYPE_HARDWARE_BUFFER,
                     -1, hardwareBuffer);
             if (id <= 0) {
                 throw new UncheckedIOException(
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index b766cd1..50dd7a0 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -989,24 +989,6 @@
 
     /**
      * 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.
@@ -1056,8 +1038,23 @@
             @VirtualDisplayFlag int flags,
             @Nullable VirtualDisplay.Callback callback,
             @Nullable Handler handler) {
-        return createVirtualDisplay(name, width, height, densityDpi, 0.0f, surface,
-                flags, handler, callback);
+        final VirtualDisplayConfig.Builder builder =
+                new VirtualDisplayConfig.Builder(name, width, height, densityDpi);
+        builder.setFlags(flags);
+        if (surface != null) {
+            builder.setSurface(surface);
+        }
+        return createVirtualDisplay(builder.build(), handler, callback);
+    }
+
+    /**
+     * Creates a virtual display.
+     *
+     * @see #createVirtualDisplay(VirtualDisplayConfig, Handler, VirtualDisplay.Callback)
+     */
+    @Nullable
+    public VirtualDisplay createVirtualDisplay(@NonNull VirtualDisplayConfig config) {
+        return createVirtualDisplay(config, /*handler=*/null, /*callback=*/null);
     }
 
     /**
@@ -1084,21 +1081,7 @@
      * 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 config The configuration of the virtual display, must be non-null.
      * @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
@@ -1106,33 +1089,14 @@
      * not create the virtual display.
      *
      * @throws SecurityException if the caller does not have permission to create
-     * a virtual display with the specified flags.
+     * a virtual display with flags specified in the configuration.
      */
     @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,
+    public VirtualDisplay createVirtualDisplay(
+            @NonNull VirtualDisplayConfig config,
             @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,
+        return createVirtualDisplay(null /* projection */, config, callback, handler,
                 null /* windowContext */);
     }
 
diff --git a/core/java/android/hardware/display/VirtualDisplayConfig.java b/core/java/android/hardware/display/VirtualDisplayConfig.java
index f6a2e33..6b56a06 100644
--- a/core/java/android/hardware/display/VirtualDisplayConfig.java
+++ b/core/java/android/hardware/display/VirtualDisplayConfig.java
@@ -18,121 +18,44 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import android.annotation.FloatRange;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.hardware.display.DisplayManager.VirtualDisplayFlag;
 import android.media.projection.MediaProjection;
+import android.os.Handler;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.view.Display;
 import android.view.Surface;
 
-import com.android.internal.util.DataClass;
-
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 
 /**
- * Holds configuration used to create {@link VirtualDisplay} instances. See
- * {@link MediaProjection#createVirtualDisplay} and
- * {@link android.companion.virtual.VirtualDeviceManager.VirtualDevice#createVirtualDisplay}.
+ * Holds configuration used to create {@link VirtualDisplay} instances.
  *
- * @hide
+ * @see DisplayManager#createVirtualDisplay(VirtualDisplayConfig, Handler, VirtualDisplay.Callback)
+ * @see MediaProjection#createVirtualDisplay
  */
-@DataClass(genParcelable = true, genAidl = true, genBuilder = true)
 public final class VirtualDisplayConfig implements Parcelable {
-    /**
-     * The name of the virtual display, must be non-empty.
-     */
-    @NonNull
-    private String mName;
 
-    /**
-     * The width of the virtual display in pixels. Must be greater than 0.
-     */
-    @IntRange(from = 1)
-    private int mWidth;
+    private final String mName;
+    private final int mWidth;
+    private final int mHeight;
+    private final int mDensityDpi;
+    private final int mFlags;
+    private final Surface mSurface;
+    private final String mUniqueId;
+    private final int mDisplayIdToMirror;
+    private final boolean mWindowManagerMirroring;
+    private ArrayList<String> mDisplayCategories = null;
+    private final float mRequestedRefreshRate;
 
-    /**
-     * The height of the virtual display in pixels. Must be greater than 0.
-     */
-    @IntRange(from = 1)
-    private int mHeight;
-
-    /**
-     * The density of the virtual display in dpi. Must be greater than 0.
-     */
-    @IntRange(from = 1)
-    private int mDensityDpi;
-
-    /**
-     * A combination of virtual display flags.
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
-     * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
-     */
-    @VirtualDisplayFlag
-    private int mFlags = 0;
-
-    /**
-     * The surface to which the content of the virtual display should be rendered, or null if
-     * there is none initially.
-     */
-    @Nullable
-    private Surface mSurface = null;
-
-    /**
-     * The unique identifier for the display. Shouldn't be displayed to the user.
-     * @hide
-     */
-    @Nullable
-    private String mUniqueId = null;
-
-    /**
-     * The id of the display that the virtual display should mirror, or
-     * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
-     */
-    private int mDisplayIdToMirror = DEFAULT_DISPLAY;
-
-    /**
-     * Indicates if WindowManager is responsible for mirroring content to this VirtualDisplay, or
-     * if DisplayManager should record contents instead.
-     */
-    private boolean mWindowManagerMirroring = false;
-
-    /**
-     * The display categories. If set, only corresponding activities from the same category can be
-     * shown on the display.
-     */
-    @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.
-    //
-    // DO NOT MODIFY!
-    // CHECKSTYLE:OFF Generated code
-    //
-    // To regenerate run:
-    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/display/VirtualDisplayConfig.java
-    //
-    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
-    //   Settings > Editor > Code Style > Formatter Control
-    //@formatter:off
-
-
-    @DataClass.Generated.Member
-    /* package-private */ VirtualDisplayConfig(
+    private VirtualDisplayConfig(
             @NonNull String name,
             @IntRange(from = 1) int width,
             @IntRange(from = 1) int height,
@@ -142,219 +65,200 @@
             @Nullable String uniqueId,
             int displayIdToMirror,
             boolean windowManagerMirroring,
-            @NonNull List<String> displayCategories,
+            @NonNull ArrayList<String> displayCategories,
             float requestedRefreshRate) {
-        this.mName = name;
-        com.android.internal.util.AnnotationValidations.validate(
-                NonNull.class, null, mName);
-        this.mWidth = width;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mWidth,
-                "from", 1);
-        this.mHeight = height;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mHeight,
-                "from", 1);
-        this.mDensityDpi = densityDpi;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mDensityDpi,
-                "from", 1);
-        this.mFlags = flags;
-        com.android.internal.util.AnnotationValidations.validate(
-                VirtualDisplayFlag.class, null, mFlags);
-        this.mSurface = surface;
-        this.mUniqueId = uniqueId;
-        this.mDisplayIdToMirror = displayIdToMirror;
-        this.mWindowManagerMirroring = windowManagerMirroring;
-        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
+        mName = name;
+        mWidth = width;
+        mHeight = height;
+        mDensityDpi = densityDpi;
+        mFlags = flags;
+        mSurface = surface;
+        mUniqueId = uniqueId;
+        mDisplayIdToMirror = displayIdToMirror;
+        mWindowManagerMirroring = windowManagerMirroring;
+        mDisplayCategories = displayCategories;
+        mRequestedRefreshRate = requestedRefreshRate;
     }
 
     /**
-     * The name of the virtual display, must be non-empty.
+     * Returns the name of the virtual display.
      */
-    @DataClass.Generated.Member
-    public @NonNull String getName() {
+    @NonNull
+    public String getName() {
         return mName;
     }
 
     /**
-     * The width of the virtual display in pixels. Must be greater than 0.
+     * Returns the width of the virtual display in pixels.
      */
-    @DataClass.Generated.Member
-    public @IntRange(from = 1) int getWidth() {
+    public int getWidth() {
         return mWidth;
     }
 
     /**
-     * The height of the virtual display in pixels. Must be greater than 0.
+     * Returns the height of the virtual display in pixels.
      */
-    @DataClass.Generated.Member
-    public @IntRange(from = 1) int getHeight() {
+    public int getHeight() {
         return mHeight;
     }
 
     /**
-     * The density of the virtual display in dpi. Must be greater than 0.
+     * Returns the density of the virtual display in dpi.
      */
-    @DataClass.Generated.Member
-    public @IntRange(from = 1) int getDensityDpi() {
+    public int getDensityDpi() {
         return mDensityDpi;
     }
 
     /**
-     * A combination of virtual display flags.
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
-     * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
-     * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
+     * Returns the virtual display flags.
+     *
+     * @see Builder#setFlags
      */
-    @DataClass.Generated.Member
-    public @VirtualDisplayFlag int getFlags() {
+    public int getFlags() {
         return mFlags;
     }
 
     /**
-     * The surface to which the content of the virtual display should be rendered, or null if
-     * there is none initially.
+     * Returns the surface to which the content of the virtual display should be rendered, if any.
+     *
+     * @see Builder#setSurface
      */
-    @DataClass.Generated.Member
-    public @Nullable Surface getSurface() {
+    @Nullable
+    public Surface getSurface() {
         return mSurface;
     }
 
     /**
-     * The unique identifier for the display. Shouldn't be displayed to the user.
-     *
+     * Returns the unique identifier for the display. Shouldn't be displayed to the user.
      * @hide
      */
-    @DataClass.Generated.Member
-    public @Nullable String getUniqueId() {
+    @Nullable
+    public String getUniqueId() {
         return mUniqueId;
     }
 
     /**
-     * The id of the display that the virtual display should mirror, or
-     * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+     * Returns the id of the display that the virtual display should mirror, or
+     * {@link android.view.Display#DEFAULT_DISPLAY} if there is none.
+     * @hide
      */
-    @DataClass.Generated.Member
     public int getDisplayIdToMirror() {
         return mDisplayIdToMirror;
     }
 
     /**
-     * Indicates if WindowManager is responsible for mirroring content to this VirtualDisplay, or
+     * Whether if WindowManager is responsible for mirroring content to this VirtualDisplay, or
      * if DisplayManager should record contents instead.
+     * @hide
      */
-    @DataClass.Generated.Member
     public boolean isWindowManagerMirroring() {
         return mWindowManagerMirroring;
     }
 
     /**
-     * The display categories. If set, only corresponding activities from the same category can be
-     * shown on the display.
+     * Returns the display categories.
+     *
+     * @see Builder#setDisplayCategories
      */
-    @DataClass.Generated.Member
-    public @NonNull List<String> getDisplayCategories() {
-        return mDisplayCategories;
+    @NonNull
+    public List<String> getDisplayCategories() {
+        return Collections.unmodifiableList(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.
+     * Returns the refresh rate of a virtual display in frames per second, or zero if it is using a
+     * default refresh rate chosen by the system.
+     *
+     * @see Builder#setRequestedRefreshRate
      */
-    @DataClass.Generated.Member
     public float getRequestedRefreshRate() {
         return mRequestedRefreshRate;
     }
 
     @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) { ... }
-
-        int flg = 0;
-        if (mWindowManagerMirroring) flg |= 0x100;
-        if (mSurface != null) flg |= 0x20;
-        if (mUniqueId != null) flg |= 0x40;
-        dest.writeInt(flg);
-        dest.writeString(mName);
+        dest.writeString8(mName);
         dest.writeInt(mWidth);
         dest.writeInt(mHeight);
         dest.writeInt(mDensityDpi);
         dest.writeInt(mFlags);
-        if (mSurface != null) dest.writeTypedObject(mSurface, flags);
-        if (mUniqueId != null) dest.writeString(mUniqueId);
+        dest.writeTypedObject(mSurface, flags);
+        dest.writeString8(mUniqueId);
         dest.writeInt(mDisplayIdToMirror);
+        dest.writeBoolean(mWindowManagerMirroring);
         dest.writeStringList(mDisplayCategories);
         dest.writeFloat(mRequestedRefreshRate);
     }
 
     @Override
-    @DataClass.Generated.Member
     public int describeContents() { return 0; }
 
-    /** @hide */
-    @SuppressWarnings({"unchecked", "RedundantCast"})
-    @DataClass.Generated.Member
-    /* package-private */ VirtualDisplayConfig(@NonNull Parcel in) {
-        // You can override field unparcelling by defining methods like:
-        // static FieldType unparcelFieldName(Parcel in) { ... }
-
-        int flg = in.readInt();
-        boolean windowManagerMirroring = (flg & 0x100) != 0;
-        String name = in.readString();
-        int width = in.readInt();
-        int height = in.readInt();
-        int densityDpi = in.readInt();
-        int flags = in.readInt();
-        Surface surface = (flg & 0x20) == 0 ? null : (Surface) in.readTypedObject(Surface.CREATOR);
-        String uniqueId = (flg & 0x40) == 0 ? null : in.readString();
-        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(
-                NonNull.class, null, mName);
-        this.mWidth = width;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mWidth,
-                "from", 1);
-        this.mHeight = height;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mHeight,
-                "from", 1);
-        this.mDensityDpi = densityDpi;
-        com.android.internal.util.AnnotationValidations.validate(
-                IntRange.class, null, mDensityDpi,
-                "from", 1);
-        this.mFlags = flags;
-        com.android.internal.util.AnnotationValidations.validate(
-                VirtualDisplayFlag.class, null, mFlags);
-        this.mSurface = surface;
-        this.mUniqueId = uniqueId;
-        this.mDisplayIdToMirror = displayIdToMirror;
-        this.mWindowManagerMirroring = windowManagerMirroring;
-        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
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof VirtualDisplayConfig)) {
+            return false;
+        }
+        VirtualDisplayConfig that = (VirtualDisplayConfig) o;
+        return Objects.equals(mName, that.mName)
+                && mWidth == that.mWidth
+                && mHeight == that.mHeight
+                && mDensityDpi == that.mDensityDpi
+                && mFlags == that.mFlags
+                && Objects.equals(mSurface, that.mSurface)
+                && Objects.equals(mUniqueId, that.mUniqueId)
+                && mDisplayIdToMirror == that.mDisplayIdToMirror
+                && mWindowManagerMirroring == that.mWindowManagerMirroring
+                && Objects.equals(mDisplayCategories, that.mDisplayCategories)
+                && mRequestedRefreshRate == that.mRequestedRefreshRate;
     }
 
-    @DataClass.Generated.Member
-    public static final @NonNull Parcelable.Creator<VirtualDisplayConfig> CREATOR
+    @Override
+    public int hashCode() {
+        int hashCode = Objects.hash(
+                mName, mWidth, mHeight, mDensityDpi, mFlags, mSurface, mUniqueId,
+                mDisplayIdToMirror, mWindowManagerMirroring, mDisplayCategories,
+                mRequestedRefreshRate);
+        return hashCode;
+    }
+
+    @Override
+    @NonNull
+    public String toString() {
+        return "VirtualDisplayConfig("
+                + " mName=" + mName
+                + " mHeight=" + mHeight
+                + " mWidth=" + mWidth
+                + " mDensityDpi=" + mDensityDpi
+                + " mFlags=" + mFlags
+                + " mSurface=" + mSurface
+                + " mUniqueId=" + mUniqueId
+                + " mDisplayIdToMirror=" + mDisplayIdToMirror
+                + " mWindowManagerMirroring=" + mWindowManagerMirroring
+                + " mDisplayCategories=" + mDisplayCategories
+                + " mRequestedRefreshRate=" + mRequestedRefreshRate
+                + ")";
+    }
+
+    private VirtualDisplayConfig(@NonNull Parcel in) {
+        mName = in.readString8();
+        mWidth = in.readInt();
+        mHeight = in.readInt();
+        mDensityDpi = in.readInt();
+        mFlags = in.readInt();
+        mSurface = in.readTypedObject(Surface.CREATOR);
+        mUniqueId = in.readString8();
+        mDisplayIdToMirror = in.readInt();
+        mWindowManagerMirroring = in.readBoolean();
+        mDisplayCategories = new ArrayList<>();
+        in.readStringList(mDisplayCategories);
+        mRequestedRefreshRate = in.readFloat();
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<VirtualDisplayConfig> CREATOR
             = new Parcelable.Creator<VirtualDisplayConfig>() {
         @Override
         public VirtualDisplayConfig[] newArray(int size) {
@@ -368,229 +272,161 @@
     };
 
     /**
-     * A builder for {@link VirtualDisplayConfig}
+     * A builder for {@link VirtualDisplayConfig}.
      */
-    @SuppressWarnings("WeakerAccess")
-    @DataClass.Generated.Member
     public static final class Builder {
-
-        private @NonNull String mName;
-        private @IntRange(from = 1) int mWidth;
-        private @IntRange(from = 1) int mHeight;
-        private @IntRange(from = 1) int mDensityDpi;
-        private @VirtualDisplayFlag int mFlags;
-        private @Nullable Surface mSurface;
-        private @Nullable String mUniqueId;
-        private int mDisplayIdToMirror;
-        private boolean mWindowManagerMirroring;
-        private @NonNull List<String> mDisplayCategories;
-        private float mRequestedRefreshRate;
-
-        private long mBuilderFieldsSet = 0L;
+        private final String mName;
+        private final int mWidth;
+        private final int mHeight;
+        private final int mDensityDpi;
+        private int mFlags = 0;
+        private Surface mSurface = null;
+        private String mUniqueId = null;
+        private int mDisplayIdToMirror = DEFAULT_DISPLAY;
+        private boolean mWindowManagerMirroring = false;
+        private ArrayList<String> mDisplayCategories = new ArrayList<>();
+        private float mRequestedRefreshRate = 0.0f;
 
         /**
          * Creates a new Builder.
          *
-         * @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 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.
          */
         public Builder(
                 @NonNull String name,
                 @IntRange(from = 1) int width,
                 @IntRange(from = 1) int height,
                 @IntRange(from = 1) int densityDpi) {
+            if (name == null) {
+                throw new IllegalArgumentException("Virtual display name is required");
+            }
+            if (width <= 0) {
+                throw new IllegalArgumentException("Virtual display width must be positive");
+            }
+            if (height <= 0) {
+                throw new IllegalArgumentException("Virtual display height must be positive");
+            }
+            if (densityDpi <= 0) {
+                throw new IllegalArgumentException("Virtual display density must be positive");
+            }
             mName = name;
-            com.android.internal.util.AnnotationValidations.validate(
-                    NonNull.class, null, mName);
             mWidth = width;
-            com.android.internal.util.AnnotationValidations.validate(
-                    IntRange.class, null, mWidth,
-                    "from", 1);
             mHeight = height;
-            com.android.internal.util.AnnotationValidations.validate(
-                    IntRange.class, null, mHeight,
-                    "from", 1);
             mDensityDpi = densityDpi;
-            com.android.internal.util.AnnotationValidations.validate(
-                    IntRange.class, null, mDensityDpi,
-                    "from", 1);
         }
 
         /**
-         * The name of the virtual display, must be non-empty.
-         */
-        @DataClass.Generated.Member
-        public @NonNull Builder setName(@NonNull String value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x1;
-            mName = value;
-            return this;
-        }
-
-        /**
-         * The width of the virtual display in pixels. Must be greater than 0.
-         */
-        @DataClass.Generated.Member
-        public @NonNull Builder setWidth(@IntRange(from = 1) int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x2;
-            mWidth = value;
-            return this;
-        }
-
-        /**
-         * The height of the virtual display in pixels. Must be greater than 0.
-         */
-        @DataClass.Generated.Member
-        public @NonNull Builder setHeight(@IntRange(from = 1) int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x4;
-            mHeight = value;
-            return this;
-        }
-
-        /**
-         * The density of the virtual display in dpi. Must be greater than 0.
-         */
-        @DataClass.Generated.Member
-        public @NonNull Builder setDensityDpi(@IntRange(from = 1) int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x8;
-            mDensityDpi = value;
-            return this;
-        }
-
-        /**
-         * A combination of virtual display flags.
+         * Sets the virtual display flags, a combination of
          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
          * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setFlags(@VirtualDisplayFlag int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x10;
-            mFlags = value;
+        @NonNull
+        public Builder setFlags(@VirtualDisplayFlag int flags) {
+            mFlags = flags;
             return this;
         }
 
         /**
-         * The surface to which the content of the virtual display should be rendered, or null if
-         * there is none initially.
-         */
-        @DataClass.Generated.Member
-        public @NonNull Builder setSurface(@NonNull Surface value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x20;
-            mSurface = value;
-            return this;
-        }
-
-        /**
-         * The unique identifier for the display. Shouldn't be displayed to the user.
+         * Sets the surface to which the content of the virtual display should be rendered.
          *
+         * <p>The surface can also be set after the display creation using
+         * {@link VirtualDisplay#setSurface(Surface)}.
+         */
+        @NonNull
+        public Builder setSurface(@Nullable Surface surface) {
+            mSurface = surface;
+            return this;
+        }
+
+        /**
+         * Sets the unique identifier for the display.
          * @hide
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setUniqueId(@NonNull String value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x40;
-            mUniqueId = value;
+        @NonNull
+        public Builder setUniqueId(@Nullable String uniqueId) {
+            mUniqueId = uniqueId;
             return this;
         }
 
         /**
-         * The id of the display that the virtual display should mirror, or
-         * {@link android.view.Display#DEFAULT_DISPLAY} if there is none initially.
+         * Sets the id of the display that the virtual display should mirror.
+         * @hide
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setDisplayIdToMirror(int value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x80;
-            mDisplayIdToMirror = value;
+        @NonNull
+        public Builder setDisplayIdToMirror(int displayIdToMirror) {
+            mDisplayIdToMirror = displayIdToMirror;
             return this;
         }
 
         /**
-         * Indicates if WindowManager is responsible for mirroring content to this VirtualDisplay, or
-         * if DisplayManager should record contents instead.
+         * Sets whether WindowManager is responsible for mirroring content to this VirtualDisplay.
+         * If unset or false, DisplayManager should record contents instead.
+         * @hide
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setWindowManagerMirroring(boolean value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x100;
-            mWindowManagerMirroring = value;
+        @NonNull
+        public Builder setWindowManagerMirroring(boolean windowManagerMirroring) {
+            mWindowManagerMirroring = windowManagerMirroring;
             return this;
         }
 
         /**
-         * The display categories. If set, only corresponding activities from the same category can be
-         * shown on the display.
+         * Sets the display categories.
+         *
+         * <p>The categories of the display indicate the type of activities allowed to run on that
+         * display. Activities can declare a display category using
+         * {@link android.content.pm.ActivityInfo#requiredDisplayCategory}.
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setDisplayCategories(@NonNull List<String> value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x200;
-            mDisplayCategories = value;
-            return this;
-        }
-
-        /** @see #setDisplayCategories */
-        @DataClass.Generated.Member
-        public @NonNull Builder addDisplayCategory(@NonNull String value) {
-            if (mDisplayCategories == null) setDisplayCategories(new ArrayList<>());
-            mDisplayCategories.add(value);
+        @NonNull
+        public Builder setDisplayCategories(@NonNull List<String> displayCategories) {
+            mDisplayCategories.clear();
+            mDisplayCategories.addAll(Objects.requireNonNull(displayCategories));
             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.
+         * Adds a display category.
+         *
+         * @see #setDisplayCategories
          */
-        @DataClass.Generated.Member
-        public @NonNull Builder setRequestedRefreshRate(float value) {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x400;
-            mRequestedRefreshRate = value;
+        @NonNull
+        public Builder addDisplayCategory(@NonNull String displayCategory) {
+            mDisplayCategories.add(Objects.requireNonNull(displayCategory));
             return this;
         }
 
-        /** Builds the instance. This builder should not be touched after calling this! */
-        public @NonNull VirtualDisplayConfig build() {
-            checkNotUsed();
-            mBuilderFieldsSet |= 0x800; // Mark builder used
+        /**
+         * Sets the refresh rate of a virtual display in frames per second.
+         *
+         * <p>For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on
+         * a 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded up
+         * down to a divisor of the physical display. If unset or zero, the virtual display will be
+         * refreshed at the physical display refresh rate.
+         *
+         * @see Display#getRefreshRate()
+         */
+        @NonNull
+        public Builder setRequestedRefreshRate(
+                @FloatRange(from = 0.0f) float requestedRefreshRate) {
+            if (requestedRefreshRate < 0.0f) {
+                throw new IllegalArgumentException(
+                        "Virtual display requested refresh rate must be non-negative");
+            }
+            mRequestedRefreshRate = requestedRefreshRate;
+            return this;
+        }
 
-            if ((mBuilderFieldsSet & 0x10) == 0) {
-                mFlags = 0;
-            }
-            if ((mBuilderFieldsSet & 0x20) == 0) {
-                mSurface = null;
-            }
-            if ((mBuilderFieldsSet & 0x40) == 0) {
-                mUniqueId = null;
-            }
-            if ((mBuilderFieldsSet & 0x80) == 0) {
-                mDisplayIdToMirror = DEFAULT_DISPLAY;
-            }
-            if ((mBuilderFieldsSet & 0x100) == 0) {
-                mWindowManagerMirroring = false;
-            }
-            if ((mBuilderFieldsSet & 0x200) == 0) {
-                mDisplayCategories = new ArrayList<>();
-            }
-            if ((mBuilderFieldsSet & 0x400) == 0) {
-                mRequestedRefreshRate = 0.0f;
-            }
-            VirtualDisplayConfig o = new VirtualDisplayConfig(
+        /**
+         * Builds the {@link VirtualDisplayConfig} instance.
+         */
+        @NonNull
+        public VirtualDisplayConfig build() {
+            return new VirtualDisplayConfig(
                     mName,
                     mWidth,
                     mHeight,
@@ -602,27 +438,6 @@
                     mWindowManagerMirroring,
                     mDisplayCategories,
                     mRequestedRefreshRate);
-            return o;
-        }
-
-        private void checkNotUsed() {
-            if ((mBuilderFieldsSet & 0x800) != 0) {
-                throw new IllegalStateException(
-                        "This Builder should not be reused. Use a new Builder instance instead");
-            }
         }
     }
-
-    @DataClass.Generated(
-            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\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() {}
-
-
-    //@formatter:on
-    // End of generated code
-
 }
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 0954013..793a70e 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -660,7 +660,7 @@
      * @param proto the ProtoOutputStream to write to
      */
     public void dumpDebug(ProtoOutputStream proto) {
-        getComponent().dumpDebug(proto, ApduServiceInfoProto.COMPONENT_NAME);
+        Utils.dumpDebugComponentName(getComponent(), proto, ApduServiceInfoProto.COMPONENT_NAME);
         proto.write(ApduServiceInfoProto.DESCRIPTION, getDescription());
         proto.write(ApduServiceInfoProto.ON_HOST, mOnHost);
         if (!mOnHost) {
diff --git a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
index f8f7dfe..7a36b26 100644
--- a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
@@ -340,7 +340,7 @@
      * @param proto the ProtoOutputStream to write to
      */
     public void dumpDebug(ProtoOutputStream proto) {
-        getComponent().dumpDebug(proto, NfcFServiceInfoProto.COMPONENT_NAME);
+        Utils.dumpDebugComponentName(getComponent(), proto, NfcFServiceInfoProto.COMPONENT_NAME);
         proto.write(NfcFServiceInfoProto.DESCRIPTION, getDescription());
         proto.write(NfcFServiceInfoProto.SYSTEM_CODE, getSystemCode());
         proto.write(NfcFServiceInfoProto.NFCID2, getNfcid2());
diff --git a/core/java/android/nfc/cardemulation/Utils.java b/core/java/android/nfc/cardemulation/Utils.java
new file mode 100644
index 0000000..202e1cf
--- /dev/null
+++ b/core/java/android/nfc/cardemulation/Utils.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 android.nfc.cardemulation;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.ComponentNameProto;
+import android.util.proto.ProtoOutputStream;
+
+/** @hide */
+public final class Utils {
+    private Utils() {
+    }
+
+    /** Copied from {@link ComponentName#dumpDebug(ProtoOutputStream, long)} */
+    public static void dumpDebugComponentName(
+            @NonNull ComponentName componentName, @NonNull ProtoOutputStream proto, long fieldId) {
+        final long token = proto.start(fieldId);
+        proto.write(ComponentNameProto.PACKAGE_NAME, componentName.getPackageName());
+        proto.write(ComponentNameProto.CLASS_NAME, componentName.getClassName());
+        proto.end(token);
+    }
+}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index de94b86..8d8deaa 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -3057,6 +3057,7 @@
      *
      * @hide
      */
+    @TestApi
     public int getDisplayIdAssignedToUser() {
         try {
             return mService.getDisplayIdAssignedToUser();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7656332..d7cd61567 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -99,7 +99,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
-import com.android.internal.widget.ILockSettings;
 
 import java.io.IOException;
 import java.lang.annotation.ElementType;
@@ -6192,9 +6191,6 @@
                 sProviderHolder,
                 Secure.class);
 
-        private static ILockSettings sLockSettings = null;
-
-        private static boolean sIsSystemProcess;
         @UnsupportedAppUsage
         private static final HashSet<String> MOVED_TO_LOCK_SETTINGS;
         @UnsupportedAppUsage
@@ -6358,35 +6354,25 @@
                 return Global.getStringForUser(resolver, name, userHandle);
             }
 
-            if (MOVED_TO_LOCK_SETTINGS.contains(name)) {
-                synchronized (Secure.class) {
-                    if (sLockSettings == null) {
-                        sLockSettings = ILockSettings.Stub.asInterface(
-                                (IBinder) ServiceManager.getService("lock_settings"));
-                        sIsSystemProcess = Process.myUid() == Process.SYSTEM_UID;
-                    }
-                }
-                if (sLockSettings != null && !sIsSystemProcess) {
-                    // No context; use the ActivityThread's context as an approximation for
-                    // determining the target API level.
-                    Application application = ActivityThread.currentApplication();
+            if (MOVED_TO_LOCK_SETTINGS.contains(name) && Process.myUid() != Process.SYSTEM_UID) {
+                // No context; use the ActivityThread's context as an approximation for
+                // determining the target API level.
+                Application application = ActivityThread.currentApplication();
 
-                    boolean isPreMnc = application != null
-                            && application.getApplicationInfo() != null
-                            && application.getApplicationInfo().targetSdkVersion
-                            <= VERSION_CODES.LOLLIPOP_MR1;
-                    if (isPreMnc) {
-                        try {
-                            return sLockSettings.getString(name, "0", userHandle);
-                        } catch (RemoteException re) {
-                            // Fall through
-                        }
-                    } else {
-                        throw new SecurityException("Settings.Secure." + name
-                                + " is deprecated and no longer accessible."
-                                + " See API documentation for potential replacements.");
-                    }
+                boolean isPreMnc = application != null
+                    && application.getApplicationInfo() != null
+                    && application.getApplicationInfo().targetSdkVersion
+                    <= VERSION_CODES.LOLLIPOP_MR1;
+                if (isPreMnc) {
+                    // Old apps used to get the three deprecated LOCK_PATTERN_* settings from
+                    // ILockSettings.getString().  For security reasons, we now just return a
+                    // stubbed-out value.  Note: the only one of these three settings actually known
+                    // to have been used was LOCK_PATTERN_ENABLED, and ILockSettings.getString()
+                    // already always returned "0" for that starting in Android 11.
+                    return "0";
                 }
+                throw new SecurityException("Settings.Secure." + name + " is deprecated and no" +
+                        " longer accessible. See API documentation for potential replacements.");
             }
 
             return sNameValueCache.getStringForUser(resolver, name, userHandle);
@@ -10792,6 +10778,15 @@
                 "low_power_warning_acknowledged";
 
         /**
+         * Whether the "first time extra battery saver warning" dialog needs to be shown
+         * (0: default) or not (1).
+         *
+         * @hide
+         */
+        public static final String EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED =
+                "extra_low_power_warning_acknowledged";
+
+        /**
          * 0 (default) Auto battery saver suggestion has not been suppressed. 1) it has been
          * suppressed.
          * @hide
@@ -15207,6 +15202,12 @@
         public static final String LOW_POWER_MODE = "low_power";
 
         /**
+         * If 1 extra low power mode is enabled.
+         * @hide
+         */
+        public static final String EXTRA_LOW_POWER_MODE = "extra_low_power";
+
+        /**
          * If 1, battery saver ({@link #LOW_POWER_MODE}) will be re-activated after the device
          * is unplugged from a charger or rebooted.
          * @hide
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 6896e02..d14abfd 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4937,4 +4937,66 @@
             return ALL_COLUMNS;
         }
     }
+
+    /**
+     * Stores incoming satellite datagrams.
+     * @hide
+     */
+    public static final class SatelliteDatagrams {
+        /**
+         * Not instantiable.
+         * @hide
+         */
+        private SatelliteDatagrams() {}
+
+        /**
+         * Provider name for Satellite Datagrams table.
+         */
+        public static final String PROVIDER_NAME = "satellite";
+
+        /**
+         * Table name for Satellite Datagrams table.
+         */
+        public static final String TABLE_NAME = "incoming_datagrams";
+
+        /**
+         * URL for satellite incoming datagrams table.
+         */
+        private static final String URL = "content://" + PROVIDER_NAME + "/" + TABLE_NAME;
+
+        /**
+         * The {@code content://} style URI for this provider.
+         * @hide
+         */
+        public static final Uri CONTENT_URI = Uri.parse(URL);
+
+        /**
+         * SatelliteProvider unique key column name is the datagram id.
+         * <P>Type: INTEGER (int)</P>
+         * @hide
+         */
+        public static final String COLUMN_UNIQUE_KEY_DATAGRAM_ID = "datagram_id";
+
+        /**
+         * SatelliteProvider column name for storing datagram.
+         * <p>TYPE: BLOB
+         * @hide
+         */
+        public static final String COLUMN_DATAGRAM = "datagram";
+
+        /** All columns in {@link SatelliteDatagrams} table. */
+        private static final List<String> ALL_COLUMNS = List.of(
+                COLUMN_UNIQUE_KEY_DATAGRAM_ID,
+                COLUMN_DATAGRAM
+        );
+
+        /**
+         * @return All columns in {@link SatelliteDatagrams} table.
+         * @hide
+         */
+        @NonNull
+        public static List<String> getAllColumns() {
+            return ALL_COLUMNS;
+        }
+    }
 }
diff --git a/core/java/android/service/voice/VisualQueryDetectionService.java b/core/java/android/service/voice/VisualQueryDetectionService.java
index 2e455c2..1783186 100644
--- a/core/java/android/service/voice/VisualQueryDetectionService.java
+++ b/core/java/android/service/voice/VisualQueryDetectionService.java
@@ -49,7 +49,7 @@
  * {@link VoiceInteractionService#createVisualQueryDetector(PersistableBundle, SharedMemory,
  * Executor, VisualQueryDetector.Callback)} is called, the system will bind the application's
  * {@link VisualQueryDetectionService}. When requested from {@link VoiceInteractionService}, the
- * system calls into the {@link VisualQueryDetectionService#onStartDetection(Callback)} to enable
+ * system calls into the {@link VisualQueryDetectionService#onStartDetection()} to enable
  * detection. This method MUST be implemented to support visual query detection service.
  *
  * Note: Methods in this class may be called concurrently.
@@ -78,6 +78,8 @@
     /** @hide */
     public static final String KEY_INITIALIZATION_STATUS = "initialization_status";
 
+    private IDetectorSessionVisualQueryDetectionCallback mRemoteCallback = null;
+
 
     private final ISandboxedDetectionService mInterface = new ISandboxedDetectionService.Stub() {
 
@@ -85,7 +87,8 @@
         public void detectWithVisualSignals(
                 IDetectorSessionVisualQueryDetectionCallback callback) {
             Log.v(TAG, "#detectWithVisualSignals");
-            VisualQueryDetectionService.this.onStartDetection(new Callback(callback));
+            mRemoteCallback = callback;
+            VisualQueryDetectionService.this.onStartDetection();
         }
 
         @Override
@@ -178,16 +181,41 @@
 
     /**
      * This is called after the service is set up and the client should open the camera and the
-     * microphone to start recognition.
-     *
-     * Called when the {@link VoiceInteractionService} requests that this service
-     * {@link HotwordDetector#startRecognition()} start recognition on audio coming directly
+     * microphone to start recognition. When the {@link VoiceInteractionService} requests that this
+     * service {@link HotwordDetector#startRecognition()} start recognition on audio coming directly
      * from the device microphone.
-     *
-     * @param callback The callback to use for responding to the detection request.
-     *
+     * <p>
+     * Signal senders that return attention and query results are also expected to be called in this
+     * method according to the detection outcomes.
+     * <p>
+     * On successful user attention, developers should call
+     * {@link VisualQueryDetectionService#gainedAttention()} to enable the streaming of the query.
+     * <p>
+     * On user attention is lost, developers should call
+     * {@link VisualQueryDetectionService#lostAttention()} to disable the streaming of the query.
+     * <p>
+     * On query is detected and ready to stream, developers should call
+     * {@link VisualQueryDetectionService#streamQuery(String)} to return detected query to the
+     * {@link VisualQueryDetector}.
+     * <p>
+     * On streamed query should be rejected, clients should call
+     * {@link VisualQueryDetectionService#rejectQuery()} to abandon query streamed to the
+     * {@link VisualQueryDetector}.
+     * <p>
+     * On streamed query is finished, clients should call
+     * {@link VisualQueryDetectionService#finishQuery()} to complete query streamed to
+     * {@link VisualQueryDetector}.
+     * <p>
+     * Before a call for {@link VisualQueryDetectionService#streamQuery(String)} is triggered,
+     * {@link VisualQueryDetectionService#gainedAttention()} MUST be called to enable the streaming
+     * of query. A query streaming is also expected to be finished by calling either
+     * {@link VisualQueryDetectionService#finishQuery()} or
+     * {@link VisualQueryDetectionService#rejectQuery()} before a new query should start streaming.
+     * When the service enters the state where query streaming should be disabled,
+     * {@link VisualQueryDetectionService#lostAttention()} MUST be called to block unnecessary
+     * streaming.
      */
-    public void onStartDetection(@NonNull Callback callback) {
+    public void onStartDetection() {
         throw new UnsupportedOperationException();
     }
 
@@ -199,118 +227,78 @@
     }
 
     /**
-     * Callback for sending out signals and returning query results.
-     *
-     * On successful user attention, developers should call {@link Callback#onAttentionGained()}
-     * to enable the streaming of the query.
-     * <p>
-     * On user attention is lost, developers should call {@link Callback#onAttentionLost()} to
-     * disable the streaming of the query.
-     * <p>
-     * On query is detected and ready to stream, developers should call
-     * {@link Callback#onQueryDetected(String)} to return detected query to the
-     * {@link VisualQueryDetector}.
-     * <p>
-     * On streamed query should be rejected, clients should call {@link Callback#onQueryRejected()}
-     * to abandon query streamed to the {@link VisualQueryDetector}.
-     * <p>
-     * On streamed query is finished, clients should call {@link Callback#onQueryFinished()} to
-     * complete query streamed to {@link VisualQueryDetector}.
-     * <p>
-     * Before a call for {@link Callback#onQueryDetected(String)} is triggered,
-     * {@link Callback#onAttentionGained()} MUST be called to enable the streaming of query. A query
-     * streaming is also expected to be finished by calling either
-     * {@link Callback#onQueryFinished()} or {@link Callback#onQueryRejected()} before a new query
-     * should start streaming. When the service enters the state where query streaming should be
-     * disabled, {@link Callback#onAttentionLost()} MUST be called to block unnecessary streaming.
+     * Informs the system that the user attention is gained so queries can be streamed.
      */
-    public static final class Callback {
-
-        // TODO: consider making the constructor a test api for testing purpose
-        public Callback() {
-            mRemoteCallback = null;
+    public final void gainedAttention() {
+        try {
+            mRemoteCallback.onAttentionGained();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
+    }
 
-        private final IDetectorSessionVisualQueryDetectionCallback mRemoteCallback;
-
-        private Callback(IDetectorSessionVisualQueryDetectionCallback remoteCallback) {
-            mRemoteCallback = remoteCallback;
+    /**
+     * Informs the system that the user attention is lost to stop streaming.
+     */
+    public final void lostAttention() {
+        try {
+            mRemoteCallback.onAttentionLost();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
+    }
 
-        /**
-         * Informs attention listener that the user attention is gained.
-         */
-        public void onAttentionGained() {
-            try {
-                mRemoteCallback.onAttentionGained();
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+    /**
+     * Informs the {@link VisualQueryDetector} with the text content being captured about the
+     * query from the audio source. {@code partialQuery} is provided to the
+     * {@link VisualQueryDetector}. This method is expected to be only triggered if
+     * {@link VisualQueryDetectionService#gainedAttention()} is called to put the service into the
+     * attention gained state.
+     *
+     * @param partialQuery Partially detected query in string.
+     * @throws IllegalStateException if method called without attention gained.
+     */
+    public final void streamQuery(@NonNull String partialQuery) throws IllegalStateException {
+        Objects.requireNonNull(partialQuery);
+        try {
+            mRemoteCallback.onQueryDetected(partialQuery);
+        } catch (RemoteException e) {
+            throw new IllegalStateException("#streamQuery must be only be triggered after "
+                    + "calling #gainedAttention to be in the attention gained state.");
         }
+    }
 
-        /**
-         * Informs attention listener that the user attention is lost.
-         */
-        public void onAttentionLost() {
-            try {
-                mRemoteCallback.onAttentionLost();
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+    /**
+     * Informs the {@link VisualQueryDetector} to abandon the streamed partial query that has
+     * been sent to {@link VisualQueryDetector}.This method is expected to be only triggered if
+     * {@link VisualQueryDetectionService#streamQuery(String)} is called to put the service into
+     * the query streaming state.
+     *
+     * @throws IllegalStateException if method called without query streamed.
+     */
+    public final void rejectQuery() throws IllegalStateException {
+        try {
+            mRemoteCallback.onQueryRejected();
+        } catch (RemoteException e) {
+            throw new IllegalStateException("#rejectQuery must be only be triggered after "
+                    + "calling #streamQuery to be in the query streaming state.");
         }
+    }
 
-        /**
-         * Informs the {@link VisualQueryDetector} with the text content being captured about the
-         * query from the audio source. {@code partialQuery} is provided to the
-         * {@link VisualQueryDetector}. This method is expected to be only triggered if
-         * {@link Callback#onAttentionGained()} is called to put the service into the attention
-         * gained state.
-         *
-         * @param partialQuery Partially detected query in string.
-         * @throws IllegalStateException if method called without attention gained.
-         */
-        public void onQueryDetected(@NonNull String partialQuery) throws IllegalStateException {
-            Objects.requireNonNull(partialQuery);
-            try {
-                mRemoteCallback.onQueryDetected(partialQuery);
-            } catch (RemoteException e) {
-                throw new IllegalStateException("#onQueryDetected must be only be triggered after "
-                        + "calling #onAttentionGained to be in the attention gained state.");
-            }
-        }
-
-        /**
-         * Informs the {@link VisualQueryDetector} to abandon the streamed partial query that has
-         * been sent to {@link VisualQueryDetector}.This method is expected to be only triggered if
-         * {@link Callback#onQueryDetected()} is called to put the service into the query streaming
-         * state.
-         *
-         * @throws IllegalStateException if method called without query streamed.
-         */
-        public void onQueryRejected() throws IllegalStateException {
-            try {
-                mRemoteCallback.onQueryRejected();
-            } catch (RemoteException e) {
-                throw new IllegalStateException("#onQueryRejected must be only be triggered after "
-                        + "calling #onQueryDetected to be in the query streaming state.");
-            }
-        }
-
-        /**
-         * Informs {@link VisualQueryDetector} with the metadata to complete the streamed partial
-         * query that has been sent to {@link VisualQueryDetector}. This method is expected to be
-         * only triggered if {@link Callback#onQueryDetected()} is called to put the service into
-         * the query streaming state.
-         *
-         * @throws IllegalStateException if method called without query streamed.
-         */
-        public void onQueryFinished() throws IllegalStateException {
-            try {
-                mRemoteCallback.onQueryFinished();
-            } catch (RemoteException e) {
-                throw new IllegalStateException("#onQueryFinished must be only be triggered after "
-                        + "calling #onQueryDetected to be in the query streaming state.");
-            }
+    /**
+     * Informs {@link VisualQueryDetector} with the metadata to complete the streamed partial
+     * query that has been sent to {@link VisualQueryDetector}. This method is expected to be
+     * only triggered if {@link VisualQueryDetectionService#streamQuery(String)} is called to put
+     * the service into the query streaming state.
+     *
+     * @throws IllegalStateException if method called without query streamed.
+     */
+    public final void finishQuery() throws IllegalStateException {
+        try {
+            mRemoteCallback.onQueryFinished();
+        } catch (RemoteException e) {
+            throw new IllegalStateException("#finishQuery must be only be triggered after "
+                    + "calling #streamQuery to be in the query streaming state.");
         }
     }
 
diff --git a/core/java/android/service/voice/VisualQueryDetector.java b/core/java/android/service/voice/VisualQueryDetector.java
index 0be3253..f0f6a4f 100644
--- a/core/java/android/service/voice/VisualQueryDetector.java
+++ b/core/java/android/service/voice/VisualQueryDetector.java
@@ -177,7 +177,8 @@
     public interface Callback {
 
         /**
-         * Called when the {@link VisualQueryDetectionService} starts to stream partial queries.
+         * Called when the {@link VisualQueryDetectionService} starts to stream partial queries
+         * with {@link VisualQueryDetectionService#streamQuery(String)}.
          *
          * @param partialQuery The partial query in a text form being streamed.
          */
@@ -185,12 +186,13 @@
 
         /**
          * Called when the {@link VisualQueryDetectionService} decides to abandon the streamed
-         * partial queries.
+         * partial queries with {@link VisualQueryDetectionService#rejectQuery()}.
          */
         void onQueryRejected();
 
         /**
-         *  Called when the {@link VisualQueryDetectionService} finishes streaming partial queries.
+         *  Called when the {@link VisualQueryDetectionService} finishes streaming partial queries
+         *  with {@link VisualQueryDetectionService#finishQuery()}.
          */
         void onQueryFinished();
 
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index f648ad4..434b1c7 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -53,9 +53,7 @@
 
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.WeakHashMap;
@@ -83,15 +81,16 @@
      * A mapping between {@link SubscriptionManager.OnSubscriptionsChangedListener} and
      * its callback IOnSubscriptionsChangedListener.
      */
-    private final Map<SubscriptionManager.OnSubscriptionsChangedListener,
-                IOnSubscriptionsChangedListener> mSubscriptionChangedListenerMap = new HashMap<>();
+    private final ConcurrentHashMap<SubscriptionManager.OnSubscriptionsChangedListener,
+            IOnSubscriptionsChangedListener>
+                    mSubscriptionChangedListenerMap = new ConcurrentHashMap<>();
     /**
      * A mapping between {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} and
      * its callback IOnSubscriptionsChangedListener.
      */
-    private final Map<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener,
-            IOnSubscriptionsChangedListener> mOpportunisticSubscriptionChangedListenerMap
-            = new HashMap<>();
+    private final ConcurrentHashMap<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener,
+            IOnSubscriptionsChangedListener>
+                    mOpportunisticSubscriptionChangedListenerMap = new ConcurrentHashMap<>();
 
     /**
      * A mapping between {@link CarrierConfigManager.CarrierConfigChangeListener} and its callback
diff --git a/core/java/android/util/SparseArrayMap.java b/core/java/android/util/SparseArrayMap.java
index 1a2c4df..b4e1f59 100644
--- a/core/java/android/util/SparseArrayMap.java
+++ b/core/java/android/util/SparseArrayMap.java
@@ -90,6 +90,14 @@
     }
 
     /**
+     * Removes the data for the keyIndex and mapIndex, if there was any.
+     * @hide
+     */
+    public void deleteAt(int keyIndex, int mapIndex) {
+        mData.valueAt(keyIndex).removeAt(mapIndex);
+    }
+
+    /**
      * Get the value associated with the int-K pair.
      */
     @Nullable
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index e02e600..3947738 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -20,7 +20,6 @@
 import static android.view.InsetsSourceProto.TYPE;
 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;
@@ -169,7 +168,7 @@
         // During drag-move and drag-resizing, the caption insets position may not get updated
         // before the app frame get updated. To layout the app content correctly during drag events,
         // we always return the insets with the corresponding height covering the top.
-        if (!CAPTION_ON_SHELL && getType() == WindowInsets.Type.captionBar()) {
+        if (getType() == WindowInsets.Type.captionBar()) {
             return Insets.of(0, frame.height(), 0, 0);
         }
         // Checks for whether there is shared edge with insets for 0-width/height window.
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 9e17620..b574ecf 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -31,6 +31,7 @@
 per-file Input*.aidl = file:/services/core/java/com/android/server/input/OWNERS
 per-file KeyEvent.java = file:/services/core/java/com/android/server/input/OWNERS
 per-file MotionEvent.java = file:/services/core/java/com/android/server/input/OWNERS
+per-file MotionPredictor.java = file:/services/core/java/com/android/server/input/OWNERS
 per-file PointerIcon.java = file:/services/core/java/com/android/server/input/OWNERS
 per-file SimulatedDpad.java = file:/services/core/java/com/android/server/input/OWNERS
 per-file BatchedInputEventReceiver.java = file:/services/core/java/com/android/server/input/OWNERS
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f430ec3..71a3a7b 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -10078,9 +10078,12 @@
     }
 
     void checkThread() {
-        if (mThread != Thread.currentThread()) {
+        Thread current = Thread.currentThread();
+        if (mThread != current) {
             throw new CalledFromWrongThreadException(
-                    "Only the original thread that created a view hierarchy can touch its views.");
+                    "Only the original thread that created a view hierarchy can touch its views."
+                            + " Expected: " + mThread.getName()
+                            + " Calling: " + current.getName());
         }
     }
 
@@ -11382,6 +11385,10 @@
             sendBackKeyEvent(KeyEvent.ACTION_DOWN);
             sendBackKeyEvent(KeyEvent.ACTION_UP);
         };
+        if (mOnBackInvokedDispatcher.hasImeOnBackInvokedDispatcher()) {
+            Log.d(TAG, "Skip registering CompatOnBackInvokedCallback on IME dispatcher");
+            return;
+        }
         mOnBackInvokedDispatcher.registerOnBackInvokedCallback(
                 OnBackInvokedDispatcher.PRIORITY_DEFAULT, mCompatOnBackInvokedCallback);
     }
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index aa631cf..9504852 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -2068,12 +2068,14 @@
      * {@link android.view.Display#INVALID_DISPLAY}, or is already being proxy-ed.
      *
      * @throws SecurityException if the app does not hold the
-     * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission.
+     * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission or the
+     * {@link Manifest.permission#CREATE_VIRTUAL_DEVICE} permission.
      *
      * @hide
      */
     @SystemApi
-    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+    @RequiresPermission(allOf = {Manifest.permission.MANAGE_ACCESSIBILITY,
+            Manifest.permission.CREATE_VIRTUAL_DEVICE})
     public boolean registerDisplayProxy(@NonNull AccessibilityDisplayProxy proxy) {
         final IAccessibilityManager service;
         synchronized (mLock) {
@@ -2096,12 +2098,14 @@
      * @return {@code true} if the proxy is successfully unregistered.
      *
      * @throws SecurityException if the app does not hold the
-     * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission.
+     * {@link Manifest.permission#MANAGE_ACCESSIBILITY} permission or the
+     * {@link Manifest.permission#CREATE_VIRTUAL_DEVICE} permission.
      *
      * @hide
      */
     @SystemApi
-    @RequiresPermission(Manifest.permission.MANAGE_ACCESSIBILITY)
+    @RequiresPermission(allOf = {Manifest.permission.MANAGE_ACCESSIBILITY,
+            Manifest.permission.CREATE_VIRTUAL_DEVICE})
     public boolean unregisterDisplayProxy(@NonNull AccessibilityDisplayProxy proxy)  {
         final IAccessibilityManager service;
         synchronized (mLock) {
diff --git a/core/java/android/view/autofill/OWNERS b/core/java/android/view/autofill/OWNERS
index 26c59a6..622b0e2 100644
--- a/core/java/android/view/autofill/OWNERS
+++ b/core/java/android/view/autofill/OWNERS
@@ -1,10 +1,6 @@
 # Bug component: 351486
 
-augale@google.com
-haoranzhang@google.com
-joannechung@google.com
-markpun@google.com
-lpeter@google.com
 simranjit@google.com
-tymtsai@google.com
+haoranzhang@google.com
+skxu@google.com
 yunicorn@google.com
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index ec1badb..8b55494 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SuppressLint;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
@@ -83,6 +84,22 @@
     public static final String ACTION_STYLUS_HANDWRITING_SETTINGS =
             "android.view.inputmethod.action.STYLUS_HANDWRITING_SETTINGS";
 
+    /**
+     * Maximal length of a component name
+     * @hide
+     */
+    @TestApi
+    public static final int COMPONENT_NAME_MAX_LENGTH = 1000;
+
+    /**
+     * The maximum amount of IMEs that are loaded per package (in order).
+     * If a package contains more IMEs, they will be ignored and cannot be enabled.
+     * @hide
+     */
+    @TestApi
+    @SuppressLint("MinMaxConstant")
+    public static final int MAX_IMES_PER_PACKAGE = 20;
+
     static final String TAG = "InputMethodInfo";
 
     /**
@@ -252,6 +269,13 @@
                     com.android.internal.R.styleable.InputMethod);
             settingsActivityComponent = sa.getString(
                     com.android.internal.R.styleable.InputMethod_settingsActivity);
+            if ((si.name != null && si.name.length() > COMPONENT_NAME_MAX_LENGTH) || (
+                    settingsActivityComponent != null
+                            && settingsActivityComponent.length() > COMPONENT_NAME_MAX_LENGTH)) {
+                throw new XmlPullParserException(
+                        "Activity name exceeds maximum of 1000 characters");
+            }
+
             isVrOnly = sa.getBoolean(com.android.internal.R.styleable.InputMethod_isVrOnly, false);
             isDefaultResId = sa.getResourceId(
                     com.android.internal.R.styleable.InputMethod_isDefault, 0);
diff --git a/core/java/android/window/ITaskOrganizer.aidl b/core/java/android/window/ITaskOrganizer.aidl
index bf9d3c2..fd86769 100644
--- a/core/java/android/window/ITaskOrganizer.aidl
+++ b/core/java/android/window/ITaskOrganizer.aidl
@@ -34,8 +34,9 @@
      * has create a starting window for the Task.
      *
      * @param info The information about the Task that's available
+     * @param appToken Token of the application being started.
      */
-    void addStartingWindow(in StartingWindowInfo info);
+    void addStartingWindow(in StartingWindowInfo info, IBinder appToken);
 
     /**
      * Called when the Task want to remove the starting window.
diff --git a/core/java/android/window/IWindowlessStartingSurfaceCallback.aidl b/core/java/android/window/IWindowlessStartingSurfaceCallback.aidl
deleted file mode 100644
index a081356..0000000
--- a/core/java/android/window/IWindowlessStartingSurfaceCallback.aidl
+++ /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 android.window;
-
-import android.view.SurfaceControl;
-
-/**
- * Interface to be invoked when a windowless starting surface added.
- *
- * @param addedSurface The starting surface.
- * {@hide}
- */
-interface IWindowlessStartingSurfaceCallback {
-    void onSurfaceAdded(in SurfaceControl addedSurface);
-}
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index 071c20f..1a58fd5 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -329,21 +329,6 @@
     }
 
     /**
-     * Get or create a TaskDescription from a RunningTaskInfo.
-     */
-    public static ActivityManager.TaskDescription getOrCreateTaskDescription(
-            ActivityManager.RunningTaskInfo runningTaskInfo) {
-        final ActivityManager.TaskDescription taskDescription;
-        if (runningTaskInfo.taskDescription != null) {
-            taskDescription = runningTaskInfo.taskDescription;
-        } else {
-            taskDescription = new ActivityManager.TaskDescription();
-            taskDescription.setBackgroundColor(WHITE);
-        }
-        return taskDescription;
-    }
-
-    /**
      * Help method to draw the snapshot on a surface.
      */
     public static void drawSnapshotOnSurface(StartingWindowInfo info, WindowManager.LayoutParams lp,
@@ -359,8 +344,13 @@
 
         final WindowManager.LayoutParams attrs = info.topOpaqueWindowLayoutParams;
         final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
-        final ActivityManager.TaskDescription taskDescription =
-                getOrCreateTaskDescription(runningTaskInfo);
+        final ActivityManager.TaskDescription taskDescription;
+        if (runningTaskInfo.taskDescription != null) {
+            taskDescription = runningTaskInfo.taskDescription;
+        } else {
+            taskDescription = new ActivityManager.TaskDescription();
+            taskDescription.setBackgroundColor(WHITE);
+        }
         drawSurface.initiateSystemBarPainter(lp.flags, lp.privateFlags,
                 attrs.insetsFlags.appearance, taskDescription, info.requestedVisibleTypes);
         final Rect systemBarInsets = getSystemBarInsets(windowBounds, topWindowInsetsState);
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 451acbe..1b64e61 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -22,12 +22,9 @@
 import android.app.ActivityManager;
 import android.app.TaskInfo;
 import android.content.pm.ActivityInfo;
-import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.RemoteException;
 import android.view.InsetsState;
-import android.view.SurfaceControl;
 import android.view.WindowInsets;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowManager;
@@ -62,8 +59,6 @@
     /** @hide **/
     public static final int STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN = 4;
 
-    public static final int STARTING_WINDOW_TYPE_WINDOWLESS = 5;
-
     /**
      * @hide
      */
@@ -72,8 +67,7 @@
             STARTING_WINDOW_TYPE_SPLASH_SCREEN,
             STARTING_WINDOW_TYPE_SNAPSHOT,
             STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN,
-            STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN,
-            STARTING_WINDOW_TYPE_WINDOWLESS
+            STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
     })
     public @interface StartingWindowType {}
 
@@ -124,7 +118,6 @@
             TYPE_PARAMETER_ACTIVITY_CREATED,
             TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN,
             TYPE_PARAMETER_ALLOW_HANDLE_SOLID_COLOR_SCREEN,
-            TYPE_PARAMETER_WINDOWLESS,
             TYPE_PARAMETER_LEGACY_SPLASH_SCREEN
     })
     public @interface StartingTypeParams {}
@@ -158,12 +151,6 @@
      * @hide
      */
     public static final int TYPE_PARAMETER_ALLOW_HANDLE_SOLID_COLOR_SCREEN = 0x00000080;
-
-    /**
-     * Windowless surface
-     */
-    public static final int TYPE_PARAMETER_WINDOWLESS = 0x00000100;
-
     /**
      * Application is allowed to use the legacy splash screen
      * @hide
@@ -195,33 +182,7 @@
      */
     public TaskSnapshot taskSnapshot;
 
-    @InsetsType public int requestedVisibleTypes = WindowInsets.Type.defaultVisible();
-
-    /**
-     * App token where the starting window should add to.
-     */
-    public IBinder appToken;
-
-    public IWindowlessStartingSurfaceCallback windowlessStartingSurfaceCallback;
-
-    /**
-     * The root surface where windowless surface should attach on.
-     */
-    public SurfaceControl rootSurface;
-
-    /**
-     * Notify windowless surface is created.
-     * @param addedSurface Created surface.
-     */
-    public void notifyAddComplete(SurfaceControl addedSurface) {
-        if (windowlessStartingSurfaceCallback != null) {
-            try {
-                windowlessStartingSurfaceCallback.onSurfaceAdded(addedSurface);
-            } catch (RemoteException e) {
-                //
-            }
-        }
-    }
+    public @InsetsType int requestedVisibleTypes = WindowInsets.Type.defaultVisible();
 
     public StartingWindowInfo() {
 
@@ -255,9 +216,6 @@
         dest.writeBoolean(isKeyguardOccluded);
         dest.writeTypedObject(taskSnapshot, flags);
         dest.writeInt(requestedVisibleTypes);
-        dest.writeStrongBinder(appToken);
-        dest.writeStrongInterface(windowlessStartingSurfaceCallback);
-        dest.writeTypedObject(rootSurface, flags);
     }
 
     void readFromParcel(@NonNull Parcel source) {
@@ -272,10 +230,6 @@
         isKeyguardOccluded = source.readBoolean();
         taskSnapshot = source.readTypedObject(TaskSnapshot.CREATOR);
         requestedVisibleTypes = source.readInt();
-        appToken = source.readStrongBinder();
-        windowlessStartingSurfaceCallback = IWindowlessStartingSurfaceCallback.Stub
-                .asInterface(source.readStrongBinder());
-        rootSurface = source.readTypedObject(SurfaceControl.CREATOR);
     }
 
     @Override
diff --git a/core/java/android/window/StartingWindowRemovalInfo.java b/core/java/android/window/StartingWindowRemovalInfo.java
index 5181236..384dacf 100644
--- a/core/java/android/window/StartingWindowRemovalInfo.java
+++ b/core/java/android/window/StartingWindowRemovalInfo.java
@@ -67,16 +67,6 @@
      */
     public float roundedCornerRadius;
 
-    /**
-     * Remove windowless surface.
-     */
-    public boolean windowlessSurface;
-
-    /**
-     * Remove immediately.
-     */
-    public boolean removeImmediately;
-
     public StartingWindowRemovalInfo() {
 
     }
@@ -97,8 +87,6 @@
         playRevealAnimation = source.readBoolean();
         deferRemoveForIme = source.readBoolean();
         roundedCornerRadius = source.readFloat();
-        windowlessSurface = source.readBoolean();
-        removeImmediately = source.readBoolean();
     }
 
     @Override
@@ -109,8 +97,6 @@
         dest.writeBoolean(playRevealAnimation);
         dest.writeBoolean(deferRemoveForIme);
         dest.writeFloat(roundedCornerRadius);
-        dest.writeBoolean(windowlessSurface);
-        dest.writeBoolean(removeImmediately);
     }
 
     @Override
@@ -119,9 +105,7 @@
                 + " frame=" + mainFrame
                 + " playRevealAnimation=" + playRevealAnimation
                 + " roundedCornerRadius=" + roundedCornerRadius
-                + " deferRemoveForIme=" + deferRemoveForIme
-                + " windowlessSurface=" + windowlessSurface
-                + " removeImmediately=" + removeImmediately + "}";
+                + " deferRemoveForIme=" + deferRemoveForIme + "}";
     }
 
     public static final @android.annotation.NonNull Creator<StartingWindowRemovalInfo> CREATOR =
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index d4728c1..02878f8 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -92,10 +92,13 @@
      * has create a starting window for the Task.
      *
      * @param info The information about the Task that's available
+     * @param appToken Token of the application being started.
+     *        context to for resources
      * @hide
      */
     @BinderThread
-    public void addStartingWindow(@NonNull StartingWindowInfo info) {}
+    public void addStartingWindow(@NonNull StartingWindowInfo info,
+            @NonNull IBinder appToken) {}
 
     /**
      * Called when the Task want to remove the starting window.
@@ -294,8 +297,9 @@
 
     private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() {
         @Override
-        public void addStartingWindow(StartingWindowInfo windowInfo) {
-            mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(windowInfo));
+        public void addStartingWindow(StartingWindowInfo windowInfo,
+                IBinder appToken) {
+            mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(windowInfo, appToken));
         }
 
         @Override
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index a8c2b2f..8066f50 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -357,6 +357,11 @@
         mImeDispatcher = imeDispatcher;
     }
 
+    /** Returns true if a non-null {@link ImeOnBackInvokedDispatcher} has been set. **/
+    public boolean hasImeOnBackInvokedDispatcher() {
+        return mImeDispatcher != null;
+    }
+
     /**
      * Class used to check whether a callback can be registered or not. This is meant to be
      * shared with {@link ProxyOnBackInvokedDispatcher} which needs to do the same checks.
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 7c237e69..ace8451 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -21,6 +21,7 @@
 import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL;
 import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK;
 import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
+import static android.content.ContentProvider.getUserIdFromUri;
 import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
 import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
 
@@ -161,6 +162,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 
 /**
  * The Chooser Activity handles intent resolution specifically for sharing intents -
@@ -1397,7 +1399,7 @@
 
             ImageView previewThumbnailView = contentPreviewLayout.findViewById(
                     R.id.content_preview_thumbnail);
-            if (previewThumbnail == null) {
+            if (!validForContentPreview(previewThumbnail)) {
                 previewThumbnailView.setVisibility(View.GONE);
             } else {
                 mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false);
@@ -1427,6 +1429,10 @@
         String action = targetIntent.getAction();
         if (Intent.ACTION_SEND.equals(action)) {
             Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM, android.net.Uri.class);
+            if (!validForContentPreview(uri)) {
+                imagePreview.setVisibility(View.GONE);
+                return contentPreviewLayout;
+            }
             imagePreview.findViewById(R.id.content_preview_image_1_large)
                     .setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
             mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0);
@@ -1436,7 +1442,7 @@
             List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, android.net.Uri.class);
             List<Uri> imageUris = new ArrayList<>();
             for (Uri uri : uris) {
-                if (isImageType(resolver.getType(uri))) {
+                if (validForContentPreview(uri) && isImageType(resolver.getType(uri))) {
                     imageUris.add(uri);
                 }
             }
@@ -1546,9 +1552,16 @@
         String action = targetIntent.getAction();
         if (Intent.ACTION_SEND.equals(action)) {
             Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM, android.net.Uri.class);
+            if (!validForContentPreview(uri)) {
+                contentPreviewLayout.setVisibility(View.GONE);
+                return contentPreviewLayout;
+            }
             loadFileUriIntoView(uri, contentPreviewLayout);
         } else {
             List<Uri> uris = targetIntent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, android.net.Uri.class);
+            uris = uris.stream()
+                    .filter(ChooserActivity::validForContentPreview)
+                    .collect(Collectors.toList());
             int uriCount = uris.size();
 
             if (uriCount == 0) {
@@ -1607,6 +1620,24 @@
         }
     }
 
+    /**
+     * Indicate if the incoming content URI should be allowed.
+     *
+     * @param uri the uri to test
+     * @return true if the URI is allowed for content preview
+     */
+    private static boolean validForContentPreview(Uri uri) throws SecurityException {
+        if (uri == null) {
+            return false;
+        }
+        int userId = getUserIdFromUri(uri, UserHandle.USER_CURRENT);
+        if (userId != UserHandle.USER_CURRENT && userId != UserHandle.myUserId()) {
+            Log.e(TAG, "dropped invalid content URI belonging to user " + userId);
+            return false;
+        }
+        return true;
+    }
+
     @VisibleForTesting
     protected boolean isImageType(String mimeType) {
         return mimeType != null && mimeType.startsWith("image/");
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 62f1599..d93fff9 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -37,6 +37,7 @@
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_UNLOCK_ENTRANCE_ANIMATION;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_OCCLUSION;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR;
@@ -240,6 +241,7 @@
     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;
+    public static final int CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION = 70;
 
     private static final int NO_STATSD_LOGGING = -1;
 
@@ -318,6 +320,7 @@
             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,
+            UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_CLOCK_MOVE_ANIMATION,
     };
 
     private static class InstanceHolder {
@@ -412,6 +415,7 @@
             CUJ_LAUNCHER_CLOSE_ALL_APPS_SWIPE,
             CUJ_LAUNCHER_CLOSE_ALL_APPS_TO_HOME,
             CUJ_IME_INSETS_ANIMATION,
+            CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface CujType {
@@ -946,6 +950,8 @@
                 return "LAUNCHER_CLOSE_ALL_APPS_TO_HOME";
             case CUJ_IME_INSETS_ANIMATION:
                 return "IME_INSETS_ANIMATION";
+            case CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION:
+                return "CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION";
         }
         return "UNKNOWN";
     }
diff --git a/core/java/com/android/internal/midi/EventScheduler.java b/core/java/com/android/internal/midi/EventScheduler.java
index 506902f6..426cd74 100644
--- a/core/java/com/android/internal/midi/EventScheduler.java
+++ b/core/java/com/android/internal/midi/EventScheduler.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.midi;
 
-import java.util.Iterator;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
@@ -26,11 +25,11 @@
  * And only one Thread can read from the buffer.
  */
 public class EventScheduler {
-    private static final long NANOS_PER_MILLI = 1000000;
+    public static final long NANOS_PER_MILLI = 1000000;
 
     private final Object mLock = new Object();
-    volatile private SortedMap<Long, FastEventQueue> mEventBuffer;
-    private FastEventQueue mEventPool = null;
+    protected volatile SortedMap<Long, FastEventQueue> mEventBuffer;
+    protected FastEventQueue mEventPool = null;
     private int mMaxPoolSize = 200;
     private boolean mClosed;
 
@@ -38,9 +37,13 @@
         mEventBuffer = new TreeMap<Long, FastEventQueue>();
     }
 
-    // If we keep at least one node in the list then it can be atomic
-    // and non-blocking.
-    private class FastEventQueue {
+    /**
+     * Class for a fast event queue.
+     *
+     * If we keep at least one node in the list then it can be atomic
+     * and non-blocking.
+     */
+    public static class FastEventQueue {
         // One thread takes from the beginning of the list.
         volatile SchedulableEvent mFirst;
         // A second thread returns events to the end of the list.
@@ -48,7 +51,7 @@
         volatile long mEventsAdded;
         volatile long mEventsRemoved;
 
-        FastEventQueue(SchedulableEvent event) {
+        public FastEventQueue(SchedulableEvent event) {
             mFirst = event;
             mLast = mFirst;
             mEventsAdded = 1;
@@ -149,7 +152,8 @@
      * @param event
      */
     public void add(SchedulableEvent event) {
-        synchronized (mLock) {
+        Object lock = getLock();
+        synchronized (lock) {
             FastEventQueue list = mEventBuffer.get(event.getTimestamp());
             if (list == null) {
                 long lowestTime = mEventBuffer.isEmpty() ? Long.MAX_VALUE
@@ -159,7 +163,7 @@
                 // If the event we added is earlier than the previous earliest
                 // event then notify any threads waiting for the next event.
                 if (event.getTimestamp() < lowestTime) {
-                    mLock.notify();
+                    lock.notify();
                 }
             } else {
                 list.add(event);
@@ -167,7 +171,7 @@
         }
     }
 
-    private SchedulableEvent removeNextEventLocked(long lowestTime) {
+    protected SchedulableEvent removeNextEventLocked(long lowestTime) {
         SchedulableEvent event;
         FastEventQueue list = mEventBuffer.get(lowestTime);
         // Remove list from tree if this is the last node.
@@ -186,7 +190,8 @@
      */
     public SchedulableEvent getNextEvent(long time) {
         SchedulableEvent event = null;
-        synchronized (mLock) {
+        Object lock = getLock();
+        synchronized (lock) {
             if (!mEventBuffer.isEmpty()) {
                 long lowestTime = mEventBuffer.firstKey();
                 // Is it time for this list to be processed?
@@ -209,7 +214,8 @@
      */
     public SchedulableEvent waitNextEvent() throws InterruptedException {
         SchedulableEvent event = null;
-        synchronized (mLock) {
+        Object lock = getLock();
+        synchronized (lock) {
             while (!mClosed) {
                 long millisToWait = Integer.MAX_VALUE;
                 if (!mEventBuffer.isEmpty()) {
@@ -231,7 +237,7 @@
                         }
                     }
                 }
-                mLock.wait((int) millisToWait);
+                lock.wait((int) millisToWait);
             }
         }
         return event;
@@ -242,10 +248,25 @@
         mEventBuffer = new TreeMap<Long, FastEventQueue>();
     }
 
+    /**
+     * Stops the EventScheduler.
+     * The subscriber calling waitNextEvent() will get one final SchedulableEvent returning null.
+     */
     public void close() {
-        synchronized (mLock) {
+        Object lock = getLock();
+        synchronized (lock) {
             mClosed = true;
-            mLock.notify();
+            lock.notify();
         }
     }
+
+    /**
+     * Gets the lock. This doesn't lock it in anyway.
+     * Subclasses can override this.
+     *
+     * @return Object
+     */
+    protected Object getLock() {
+        return mLock;
+    }
 }
diff --git a/core/java/com/android/internal/midi/MidiEventMultiScheduler.java b/core/java/com/android/internal/midi/MidiEventMultiScheduler.java
new file mode 100644
index 0000000..16e4abe
--- /dev/null
+++ b/core/java/com/android/internal/midi/MidiEventMultiScheduler.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.midi;
+
+/**
+ * Uses multiple MidiEventSchedulers for waiting for events.
+ *
+ */
+public class MidiEventMultiScheduler {
+    private MultiLockMidiEventScheduler[] mMidiEventSchedulers;
+    private int mNumEventSchedulers;
+    private int mNumClosedSchedulers = 0;
+    private final Object mMultiLock = new Object();
+
+    private class MultiLockMidiEventScheduler extends MidiEventScheduler {
+        @Override
+        public void close() {
+            synchronized (mMultiLock) {
+                mNumClosedSchedulers++;
+            }
+            super.close();
+        }
+
+        @Override
+        protected Object getLock() {
+            return mMultiLock;
+        }
+
+        public boolean isEventBufferEmptyLocked() {
+            return mEventBuffer.isEmpty();
+        }
+
+        public long getLowestTimeLocked() {
+            return mEventBuffer.firstKey();
+        }
+    }
+
+    /**
+     * MidiEventMultiScheduler constructor
+     *
+     * @param numSchedulers the number of schedulers to create
+     */
+    public MidiEventMultiScheduler(int numSchedulers) {
+        mNumEventSchedulers = numSchedulers;
+        mMidiEventSchedulers = new MultiLockMidiEventScheduler[numSchedulers];
+        for (int i = 0; i < numSchedulers; i++) {
+            mMidiEventSchedulers[i] = new MultiLockMidiEventScheduler();
+        }
+    }
+
+    /**
+     * Waits for the next MIDI event. This will return true when it receives it.
+     * If all MidiEventSchedulers have been closed, this will return false.
+     *
+     * @return true if a MIDI event is received and false if all schedulers are closed.
+     */
+    public boolean waitNextEvent() throws InterruptedException {
+        synchronized (mMultiLock) {
+            while (true) {
+                if (mNumClosedSchedulers >= mNumEventSchedulers) {
+                    return false;
+                }
+                long lowestTime = Long.MAX_VALUE;
+                long now = System.nanoTime();
+                for (MultiLockMidiEventScheduler eventScheduler : mMidiEventSchedulers) {
+                    if (!eventScheduler.isEventBufferEmptyLocked()) {
+                        lowestTime = Math.min(lowestTime,
+                                eventScheduler.getLowestTimeLocked());
+                    }
+                }
+                if (lowestTime <= now) {
+                    return true;
+                }
+                long nanosToWait = lowestTime - now;
+                // Add 1 millisecond so we don't wake up before it is
+                // ready.
+                long millisToWait = 1 + (nanosToWait / EventScheduler.NANOS_PER_MILLI);
+                // Clip 64-bit value to 32-bit max.
+                if (millisToWait > Integer.MAX_VALUE) {
+                    millisToWait = Integer.MAX_VALUE;
+                }
+                mMultiLock.wait(millisToWait);
+            }
+        }
+    }
+
+    /**
+     * Gets the number of MidiEventSchedulers.
+     *
+     * @return the number of MidiEventSchedulers.
+     */
+    public int getNumEventSchedulers() {
+        return mNumEventSchedulers;
+    }
+
+    /**
+     * Gets a specific MidiEventScheduler based on the index.
+     *
+     * @param index the zero indexed index of a MIDI event scheduler
+     * @return a MidiEventScheduler
+     */
+    public MidiEventScheduler getEventScheduler(int index) {
+        return mMidiEventSchedulers[index];
+    }
+
+    /**
+     * Closes all event schedulers.
+     */
+    public void close() {
+        for (MidiEventScheduler eventScheduler : mMidiEventSchedulers) {
+            eventScheduler.close();
+        }
+    }
+}
diff --git a/core/java/com/android/internal/midi/MidiEventScheduler.java b/core/java/com/android/internal/midi/MidiEventScheduler.java
index 7b01904..1b2934d 100644
--- a/core/java/com/android/internal/midi/MidiEventScheduler.java
+++ b/core/java/com/android/internal/midi/MidiEventScheduler.java
@@ -79,7 +79,7 @@
     /**
      * Create an event that contains the message.
      */
-    private MidiEvent createScheduledEvent(byte[] msg, int offset, int count,
+    public MidiEvent createScheduledEvent(byte[] msg, int offset, int count,
             long timestamp) {
         MidiEvent event;
         if (count > POOL_EVENT_SIZE) {
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 8a9445d..28b98d6 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -16,14 +16,10 @@
 
 package com.android.internal.os;
 
-import static com.android.internal.os.SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL;
-
-import android.annotation.TestApi;
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.ApplicationErrorReport;
 import android.app.IActivityManager;
-import android.app.compat.CompatChanges;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.type.DefaultMimeMapFactory;
 import android.net.TrafficStats;
@@ -40,7 +36,6 @@
 
 import dalvik.system.RuntimeHooks;
 import dalvik.system.VMRuntime;
-import dalvik.system.ZipPathValidator;
 
 import libcore.content.type.MimeMap;
 
@@ -265,31 +260,10 @@
          */
         TrafficStats.attachSocketTagger();
 
-        /*
-         * Initialize the zip path validator callback depending on the targetSdk.
-         */
-        initZipPathValidatorCallback();
-
         initialized = true;
     }
 
     /**
-     * If targetSDK >= U: set the safe zip path validator callback which disallows dangerous zip
-     * entry names.
-     * Otherwise: clear the callback to the default validation.
-     *
-     * @hide
-     */
-    @TestApi
-    public static void initZipPathValidatorCallback() {
-        if (CompatChanges.isChangeEnabled(VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL)) {
-            ZipPathValidator.setCallback(new SafeZipPathValidatorCallback());
-        } else {
-            ZipPathValidator.clearCallback();
-        }
-    }
-
-    /**
      * Returns an HTTP user agent of the form
      * "Dalvik/1.1.0 (Linux; U; Android Eclair Build/MAIN)".
      */
diff --git a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java b/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
index cd55d32..f2b0544 100644
--- a/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/BaseProtoLogImpl.java
@@ -259,6 +259,7 @@
             if (writeToFile) {
                 writeProtoLogToFileLocked();
                 logAndPrintln(pw, "Log written to " + mLogFile + ".");
+                mBuffer.resetBuffer();
             }
             if (mProtoLogEnabled) {
                 logAndPrintln(pw, "ERROR: logging was re-enabled while waiting for flush.");
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index f72c4c3..59f6d2b 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -170,6 +170,8 @@
     private static final String LOCK_SCREEN_OWNER_INFO_ENABLED =
             Settings.Secure.LOCK_SCREEN_OWNER_INFO_ENABLED;
 
+    private static final String LOCK_PIN_ENHANCED_PRIVACY = "pin_enhanced_privacy";
+
     private static final String LOCK_SCREEN_DEVICE_OWNER_INFO = "lockscreen.device_owner_info";
 
     private static final String ENABLED_TRUST_AGENTS = "lockscreen.enabledtrustagents";
@@ -1037,6 +1039,27 @@
     }
 
     /**
+     * @return Whether enhanced pin privacy is enabled.
+     */
+    public boolean isPinEnhancedPrivacyEnabled(int userId) {
+        return getBoolean(LOCK_PIN_ENHANCED_PRIVACY, false, userId);
+    }
+
+    /**
+     * Set whether enhanced pin privacy is enabled.
+     */
+    public void setPinEnhancedPrivacyEnabled(boolean enabled, int userId) {
+        setBoolean(LOCK_PIN_ENHANCED_PRIVACY, enabled, userId);
+    }
+
+    /**
+     * @return Whether enhanced pin privacy was ever chosen.
+     */
+    public boolean isPinEnhancedPrivacyEverChosen(int userId) {
+        return getString(LOCK_PIN_ENHANCED_PRIVACY, userId) != null;
+    }
+
+    /**
      * Set whether the visible password is enabled for cryptkeeper screen.
      */
     public void setVisiblePasswordEnabled(boolean enabled, int userId) {
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 939a0e4..9c6a534 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -266,7 +266,8 @@
 }
 
 static jint nativeCreateDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
-        jlong size, jint channelType, jint fd, jobject hardwareBufferObj) {
+                                      jint deviceId, jlong size, jint channelType, jint fd,
+                                      jobject hardwareBufferObj) {
     const native_handle_t *nativeHandle = nullptr;
     NATIVE_HANDLE_DECLARE_STORAGE(ashmemHandle, 1, 0);
 
@@ -287,7 +288,7 @@
     }
 
     SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
-    return mgr->createDirectChannel(size, channelType, nativeHandle);
+    return mgr->createDirectChannel(deviceId, size, channelType, nativeHandle);
 }
 
 static void nativeDestroyDirectChannel(JNIEnv *_env, jclass _this, jlong sensorManager,
@@ -532,7 +533,7 @@
 
         {"nativeIsDataInjectionEnabled", "(J)Z", (void *)nativeIsDataInjectionEnabled},
 
-        {"nativeCreateDirectChannel", "(JJIILandroid/hardware/HardwareBuffer;)I",
+        {"nativeCreateDirectChannel", "(JIJIILandroid/hardware/HardwareBuffer;)I",
          (void *)nativeCreateDirectChannel},
 
         {"nativeDestroyDirectChannel", "(JI)V", (void *)nativeDestroyDirectChannel},
diff --git a/core/proto/android/nfc/Android.bp b/core/proto/android/nfc/Android.bp
new file mode 100644
index 0000000..6a62c91
--- /dev/null
+++ b/core/proto/android/nfc/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2023 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+filegroup {
+    name: "srcs_nfc_proto",
+    srcs: [
+        "*.proto",
+    ],
+}
+
+// Will be statically linked by `framework-nfc`.
+java_library {
+    name: "nfc-proto-java-gen",
+    installable: false,
+    proto: {
+        type: "stream",
+        include_dirs: [
+            "external/protobuf/src",
+        ],
+    },
+    srcs: [
+        ":srcs_nfc_proto",
+    ],
+    sdk_version: "current",
+    min_sdk_version: "current",
+}
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index e029af4..f87d910 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -285,22 +285,24 @@
     repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
 }
 
+// Enum used in DNDModeProto to specify the zen mode setting.
+enum LoggedZenMode {
+    ROOT_CONFIG = -1;  // Used to distinguish config (one per user) from the rules.
+    OFF = 0;
+    IMPORTANT_INTERRUPTIONS = 1;
+    NO_INTERRUPTIONS = 2;
+    ALARMS = 3;
+}
+
 /**
  * Atom that represents an item in the list of Do Not Disturb rules, pulled from
  * NotificationManagerService.java.
  */
 message DNDModeProto {
-    enum Mode {
-        ROOT_CONFIG = -1;  // Used to distinguish the config (one per user) from the rules.
-        ZEN_MODE_OFF = 0;
-        ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
-        ZEN_MODE_NO_INTERRUPTIONS = 2;
-        ZEN_MODE_ALARMS = 3;
-    }
     optional int32 user = 1;  // Android user ID (0, 1, 10, ...)
     optional bool enabled = 2;  // true for ROOT_CONFIG if a manualRule is enabled
     optional bool channels_bypassing = 3; // only valid for ROOT_CONFIG
-    optional Mode zen_mode = 4;
+    optional LoggedZenMode zen_mode = 4;
     // id is one of the system default rule IDs, or empty
     // May also be "MANUAL_RULE" to indicate app-activation of the manual rule.
     optional string id = 5;
@@ -308,15 +310,34 @@
     optional DNDPolicyProto policy = 7;
 }
 
+// Enum used in DNDPolicyProto for a particular policy parameter's state.
+enum State {
+    STATE_UNSET = 0;
+    STATE_ALLOW = 1;
+    STATE_DISALLOW = 2;
+}
+
+// Enum used in DNDPolicyProto for which people are allowed to break through.
+enum PeopleType {
+    PEOPLE_UNSET = 0;
+    PEOPLE_ANYONE = 1;
+    PEOPLE_CONTACTS = 2;
+    PEOPLE_STARRED = 3;
+    PEOPLE_NONE = 4;
+}
+
+// Enum used in DNDPolicyProto for conversation types allowed to break through.
+enum ConversationType {
+    CONV_UNSET = 0;
+    CONV_ANYONE = 1;
+    CONV_IMPORTANT = 2;
+    CONV_NONE = 3;
+}
+
 /**
- * Atom that represents a Do Not Disturb policy, an optional detail proto for DNDModeProto.
+ * Message that represents a Do Not Disturb policy, an optional detail proto for DNDModeProto.
  */
 message DNDPolicyProto {
-    enum State {
-        STATE_UNSET = 0;
-        STATE_ALLOW = 1;
-        STATE_DISALLOW = 2;
-    }
     optional State calls = 1;
     optional State repeat_callers = 2;
     optional State messages = 3;
@@ -334,23 +355,8 @@
     optional State ambient = 15;
     optional State notification_list = 16;
 
-    enum PeopleType {
-        PEOPLE_UNSET = 0;
-        PEOPLE_ANYONE = 1;
-        PEOPLE_CONTACTS = 2;
-        PEOPLE_STARRED = 3;
-        PEOPLE_NONE = 4;
-    }
-
     optional PeopleType allow_calls_from = 17;
     optional PeopleType allow_messages_from = 18;
 
-    enum ConversationType {
-        CONV_UNSET = 0;
-        CONV_ANYONE = 1;
-        CONV_IMPORTANT = 2;
-        CONV_NONE = 3;
-    }
-
     optional ConversationType allow_conversations_from = 19;
 }
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 76b39bb..70464d8 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -207,12 +207,9 @@
     <string name="personal_apps_suspension_text" msgid="6115455688932935597">"Aplikazio pertsonalak blokeatuta egongo dira laneko profila aktibatzen duzun arte"</string>
     <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Aplikazio pertsonalak egun eta ordu honetan blokeatuko dira: <xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>. IKT saileko administratzaileak ez dizu ematen baimenik laneko profila <xliff:g id="NUMBER">%3$d</xliff:g> egunez baino gehiagoz desaktibatuta edukitzeko."</string>
     <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Aktibatu"</string>
-    <!-- no translation found for work_profile_telephony_paused_title (7690804479291839519) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_text (8065762301100978221) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_turn_on_button (7542632318337068821) -->
-    <skip />
+    <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Deiak eta mezuak desaktibatuta daude"</string>
+    <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Laneko aplikazioak pausatu dituzu. Ez duzu jasoko telefono-deirik edo testu-mezurik."</string>
+    <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Berraktibatu laneko aplikazioak"</string>
     <string name="me" msgid="6207584824693813140">"Ni"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Tabletaren aukerak"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV gailuaren aukerak"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index dfb0b2e..562560e 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -296,7 +296,7 @@
     <string name="safeMode" msgid="8974401416068943888">"حالت ایمن"</string>
     <string name="android_system_label" msgid="5974767339591067210">"‏سیستم Android"</string>
     <string name="user_owner_label" msgid="8628726904184471211">"جابه‌جا شدن به نمایه شخصی"</string>
-    <string name="managed_profile_label" msgid="7316778766973512382">"جابه‌جا شدن به نمایه کاری"</string>
+    <string name="managed_profile_label" msgid="7316778766973512382">"رفتن به نمایه کاری"</string>
     <string name="permgrouplab_contacts" msgid="4254143639307316920">"مخاطبین"</string>
     <string name="permgroupdesc_contacts" msgid="9163927941244182567">"دسترسی به مخاطبین شما"</string>
     <string name="permgrouplab_location" msgid="1858277002233964394">"مکان"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 0c4dfae..b8a364b 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -208,12 +208,9 @@
     <string name="personal_apps_suspension_text" msgid="6115455688932935597">"Vos applications personnelles sont bloquées jusqu\'à ce que vous activiez votre profil professionnel"</string>
     <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"Les applications personnelles seront bloquées le <xliff:g id="DATE">%1$s</xliff:g> à <xliff:g id="TIME">%2$s</xliff:g>. Votre administrateur informatique ne vous autorise pas à laisser votre profil professionnel désactivé pendant plus de <xliff:g id="NUMBER">%3$d</xliff:g> jours."</string>
     <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"Activer"</string>
-    <!-- no translation found for work_profile_telephony_paused_title (7690804479291839519) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_text (8065762301100978221) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_turn_on_button (7542632318337068821) -->
-    <skip />
+    <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"Les appels et messages sont désactivés"</string>
+    <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"Vous avez mis en pause les applications professionnelles. Vous ne recevrez aucun appel téléphonique ni message texte."</string>
+    <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"Réact. applis prof."</string>
     <string name="me" msgid="6207584824693813140">"Moi"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"Options de la tablette"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Options d\'Android TV"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 706e920..7169464 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1960,7 +1960,7 @@
     <string name="app_streaming_blocked_title" msgid="6090945835898766139">"<xliff:g id="ACTIVITY">%1$s</xliff:g>՝ անհասանելի է"</string>
     <string name="app_streaming_blocked_title_for_permission_dialog" msgid="4483161748582966785">"Անհրաժեշտ է թույլտվություն"</string>
     <string name="app_streaming_blocked_title_for_camera_dialog" msgid="3935701653713853065">"Տեսախցիկն անհասանելի է"</string>
-    <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարունակեք հեռախոսով"</string>
+    <string name="app_streaming_blocked_title_for_fingerprint_dialog" msgid="3516853717714141951">"Շարու­նակեք հեռախոսով"</string>
     <string name="app_streaming_blocked_title_for_microphone_dialog" msgid="544822455127171206">"Խոսափողն անհասանելի է"</string>
     <string name="app_streaming_blocked_title_for_playstore_dialog" msgid="8149823099822897538">"Play Խանութը հասանելի չէ"</string>
     <string name="app_streaming_blocked_title_for_settings_dialog" product="tv" msgid="196994247017450357">"Android TV-ի կարգավորումներն անհասանելի են"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index bd29ffb..a587864 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1985,7 +1985,7 @@
     <string name="profile_encrypted_message" msgid="1128512616293157802">"Tocca per sbloc. prof. di lav."</string>
     <string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Connesso a <xliff:g id="PRODUCT_NAME">%1$s</xliff:g>"</string>
     <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Tocca per visualizzare i file"</string>
-    <string name="pin_target" msgid="8036028973110156895">"Blocca"</string>
+    <string name="pin_target" msgid="8036028973110156895">"Fissa"</string>
     <string name="pin_specific_target" msgid="7824671240625957415">"Blocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
     <string name="unpin_target" msgid="3963318576590204447">"Sgancia"</string>
     <string name="unpin_specific_target" msgid="3859828252160908146">"Sblocca <xliff:g id="LABEL">%1$s</xliff:g>"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8064eb0..348dcd5 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -207,12 +207,9 @@
     <string name="personal_apps_suspension_text" msgid="6115455688932935597">"직장 프로필을 사용 설정할 때까지 개인 앱이 차단됩니다."</string>
     <string name="personal_apps_suspension_soon_text" msgid="8123898693479590">"개인 앱이 <xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>에 차단됩니다. IT 관리자가 <xliff:g id="NUMBER">%3$d</xliff:g>일 넘게 직장 프로필을 중지하도록 허용하지 않습니다."</string>
     <string name="personal_apps_suspended_turn_profile_on" msgid="2758012869627513689">"사용 설정"</string>
-    <!-- no translation found for work_profile_telephony_paused_title (7690804479291839519) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_text (8065762301100978221) -->
-    <skip />
-    <!-- no translation found for work_profile_telephony_paused_turn_on_button (7542632318337068821) -->
-    <skip />
+    <string name="work_profile_telephony_paused_title" msgid="7690804479291839519">"전화 및 메시지 사용 중지됨"</string>
+    <string name="work_profile_telephony_paused_text" msgid="8065762301100978221">"직장 앱을 일시중지했습니다. 전화나 문자 메시지를 수신하지 않습니다."</string>
+    <string name="work_profile_telephony_paused_turn_on_button" msgid="7542632318337068821">"직장 앱 일시중지 해제"</string>
     <string name="me" msgid="6207584824693813140">"나"</string>
     <string name="power_dialog" product="tablet" msgid="8333207765671417261">"태블릿 옵션"</string>
     <string name="power_dialog" product="tv" msgid="7792839006640933763">"Android TV 옵션"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 3888e0c..047d126 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1172,8 +1172,8 @@
     <string name="no" msgid="5122037903299899715">"Отмена"</string>
     <string name="dialog_alert_title" msgid="651856561974090712">"Внимание!"</string>
     <string name="loading" msgid="3138021523725055037">"Загрузка…"</string>
-    <string name="capital_on" msgid="2770685323900821829">"I"</string>
-    <string name="capital_off" msgid="7443704171014626777">"O"</string>
+    <string name="capital_on" msgid="2770685323900821829">"Включено"</string>
+    <string name="capital_off" msgid="7443704171014626777">"Выключено"</string>
     <string name="checked" msgid="9179896827054513119">"отмечено"</string>
     <string name="not_checked" msgid="7972320087569023342">"не отмечено"</string>
     <string name="selected" msgid="6614607926197755875">"выбрано"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2f94ed7..733e0ea 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1158,14 +1158,25 @@
     <integer name="config_triplePressOnStemPrimaryBehavior">0</integer>
 
     <!-- Control the behavior when the user short presses the stem primary button.
-        Stem primary button is only used on watch form factor. If a device is not
-        a watch, setting this config is no-op.
-           0 - Nothing
-           1 - Go to launch all apps
+         Stem primary button is only used on watch form factor. If a device is not
+         a watch, setting this config is no-op.
+            0 - Nothing
+            1 - Go to launch all apps
     -->
     <integer name="config_shortPressOnStemPrimaryBehavior">0</integer>
 
 
+    <!-- Control the behavior of the search key.
+            0 - Launch default search activity
+            1 - Launch target activity defined by config_searchKeyTargetActivity
+    -->
+    <integer name="config_searchKeyBehavior">0</integer>
+
+    <!-- Component name for the default target activity to be launched when user
+         presses the global search key. [DO NOT TRANSLATE]
+    -->
+    <string name="config_searchKeyTargetActivity" translatable="false"></string>
+
     <!-- Time to wait while a button is pressed before triggering a very long press. -->
     <integer name="config_veryLongPressTimeout">3500</integer>
 
@@ -1304,6 +1315,13 @@
     <!-- Default LED off time for notification LED in milliseconds. -->
     <integer name="config_defaultNotificationLedOff">2000</integer>
 
+    <!-- LED behavior when battery is low.
+         Color for solid is taken from config_notificationsBatteryLowARGB
+          0 - default, solid when charging, flashing when not charging
+          1 - always solid when battery is low
+          2 - always flashing when battery is low -->
+    <integer name="config_notificationsBatteryLowBehavior">0</integer>
+
     <!-- Default value for led color when battery is low on charge -->
     <integer name="config_notificationsBatteryLowARGB">0xFFFF0000</integer>
 
@@ -2780,8 +2798,10 @@
     <integer name="config_userTypePackageWhitelistMode">13</integer> <!-- 1+4+8 -->
 
     <!-- Whether the main user is a permanent admin user. If the main user is a permanent admin user
-     it can't be deleted or downgraded to non-admin status. -->
-    <bool name="config_isMainUserPermanentAdmin">false</bool>
+     it can't be deleted or downgraded to non-admin status.
+     This is generally only relevant on headless system user mode devices; on other devices, the
+     main user is the system user which is always a permanent admin anyway. -->
+    <bool name="config_isMainUserPermanentAdmin">true</bool>
 
     <!-- Whether switch to headless system user is allowed. If allowed,
     headless system user can run in the foreground even though it is not a full user. -->
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index 24a7d85..973b3a7 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -110,6 +110,10 @@
     <string name="config_satellite_service_package" translatable="false"></string>
     <java-symbol type="string" name="config_satellite_service_package" />
 
+    <!-- Telephony pointing UI package name to be launched. -->
+    <string name="config_pointing_ui_package" translatable="false"></string>
+    <java-symbol type="string" name="config_pointing_ui_package" />
+
     <!-- Whether enhanced IWLAN handover check is enabled. If enabled, telephony frameworks
          will not perform handover if the target transport is out of service, or VoPS not
          supported. The network will be torn down on the source transport, and will be
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 12646a0..e2b46d0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -464,6 +464,8 @@
   <java-symbol type="integer" name="config_doublePressOnStemPrimaryBehavior" />
   <java-symbol type="integer" name="config_triplePressOnStemPrimaryBehavior" />
   <java-symbol type="string" name="config_doublePressOnPowerTargetActivity" />
+  <java-symbol type="integer" name="config_searchKeyBehavior" />
+  <java-symbol type="string" name="config_searchKeyTargetActivity" />
   <java-symbol type="integer" name="config_windowOutsetBottom" />
   <java-symbol type="integer" name="db_connection_pool_size" />
   <java-symbol type="integer" name="db_journal_size_limit" />
@@ -2004,6 +2006,7 @@
   <java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
   <java-symbol type="integer" name="config_notificationsBatteryLedOff" />
   <java-symbol type="integer" name="config_notificationsBatteryLedOn" />
+  <java-symbol type="integer" name="config_notificationsBatteryLowBehavior" />
   <java-symbol type="integer" name="config_notificationsBatteryLowARGB" />
   <java-symbol type="integer" name="config_notificationsBatteryMediumARGB" />
   <java-symbol type="integer" name="config_notificationsBatteryNearlyFullLevel" />
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index e164e08..4f91e7a 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -16,7 +16,7 @@
 
 package android.app.activity;
 
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_INVALID;
+import static android.content.Context.DEVICE_ID_INVALID;
 import static android.content.Intent.ACTION_EDIT;
 import static android.content.Intent.ACTION_VIEW;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
diff --git a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java b/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
index f97099d..16ed3ef 100644
--- a/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
+++ b/core/tests/coretests/src/android/companion/virtual/sensor/VirtualSensorConfigTest.java
@@ -17,9 +17,15 @@
 package android.companion.virtual.sensor;
 
 import static android.hardware.Sensor.TYPE_ACCELEROMETER;
+import static android.hardware.SensorDirectChannel.RATE_STOP;
+import static android.hardware.SensorDirectChannel.RATE_VERY_FAST;
+import static android.hardware.SensorDirectChannel.TYPE_HARDWARE_BUFFER;
+import static android.hardware.SensorDirectChannel.TYPE_MEMORY_FILE;
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.testng.Assert.assertThrows;
+
 import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
 
@@ -40,6 +46,8 @@
         final VirtualSensorConfig originalConfig =
                 new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME)
                         .setVendor(SENSOR_VENDOR)
+                        .setHighestDirectReportRateLevel(RATE_VERY_FAST)
+                        .setDirectChannelTypesSupported(TYPE_MEMORY_FILE)
                         .build();
         final Parcel parcel = Parcel.obtain();
         originalConfig.writeToParcel(parcel, /* flags= */ 0);
@@ -49,6 +57,39 @@
         assertThat(recreatedConfig.getType()).isEqualTo(originalConfig.getType());
         assertThat(recreatedConfig.getName()).isEqualTo(originalConfig.getName());
         assertThat(recreatedConfig.getVendor()).isEqualTo(originalConfig.getVendor());
+        assertThat(recreatedConfig.getHighestDirectReportRateLevel()).isEqualTo(RATE_VERY_FAST);
+        assertThat(recreatedConfig.getDirectChannelTypesSupported()).isEqualTo(TYPE_MEMORY_FILE);
+        // From hardware/libhardware/include/hardware/sensors-base.h:
+        //   0x400 is SENSOR_FLAG_DIRECT_CHANNEL_ASHMEM (i.e. TYPE_MEMORY_FILE)
+        //   0x800 is SENSOR_FLAG_DIRECT_CHANNEL_GRALLOC (i.e. TYPE_HARDWARE_BUFFER)
+        //   7 is SENSOR_FLAG_SHIFT_DIRECT_REPORT
+        assertThat(recreatedConfig.getFlags()).isEqualTo(0x400 | RATE_VERY_FAST << 7);
+    }
+
+    @Test
+    public void hardwareBufferDirectChannelTypeSupported_throwsException() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME)
+                        .setDirectChannelTypesSupported(TYPE_HARDWARE_BUFFER | TYPE_MEMORY_FILE));
+    }
+
+    @Test
+    public void directChannelTypeSupported_missingHighestReportRateLevel_throwsException() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME)
+                        .setDirectChannelTypesSupported(TYPE_MEMORY_FILE)
+                        .build());
+    }
+
+    @Test
+    public void directChannelTypeSupported_missingDirectChannelTypeSupported_throwsException() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME)
+                        .setHighestDirectReportRateLevel(RATE_VERY_FAST)
+                        .build());
     }
 
     @Test
@@ -56,5 +97,8 @@
         final VirtualSensorConfig config =
                 new VirtualSensorConfig.Builder(TYPE_ACCELEROMETER, SENSOR_NAME).build();
         assertThat(config.getVendor()).isNull();
+        assertThat(config.getHighestDirectReportRateLevel()).isEqualTo(RATE_STOP);
+        assertThat(config.getDirectChannelTypesSupported()).isEqualTo(0);
+        assertThat(config.getFlags()).isEqualTo(0);
     }
 }
diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java
index 324f810..d478437 100644
--- a/core/tests/coretests/src/android/content/ContextTest.java
+++ b/core/tests/coretests/src/android/content/ContextTest.java
@@ -16,7 +16,7 @@
 
 package android.content;
 
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
+import static android.content.Context.DEVICE_ID_DEFAULT;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
 import static android.view.Display.DEFAULT_DISPLAY;
diff --git a/core/tests/coretests/src/android/content/pm/UserPackageTest.java b/core/tests/coretests/src/android/content/pm/UserPackageTest.java
new file mode 100644
index 0000000..5114e2cf
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/UserPackageTest.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 android.content.pm;
+
+import android.platform.test.annotations.Presubmit;
+
+import junit.framework.TestCase;
+
+@Presubmit
+public class UserPackageTest extends TestCase {
+    public void testCacheLimit() {
+        UserPackage.setValidUserIds(new int[]{0});
+        for (int i = 0; i < UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER; ++i) {
+            UserPackage.of(0, "app" + i);
+            assertEquals(i + 1, UserPackage.numEntriesForUser(0));
+        }
+
+        for (int i = 0; i < UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER; ++i) {
+            UserPackage.of(0, "appOverLimit" + i);
+            final int numCached = UserPackage.numEntriesForUser(0);
+            assertTrue(numCached >= 1);
+            assertTrue(numCached <= UserPackage.MAX_NUM_CACHED_ENTRIES_PER_USER);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
index ef106bc..ee1b2aa 100644
--- a/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
+++ b/core/tests/coretests/src/android/content/res/FontScaleConverterFactoryTest.kt
@@ -43,14 +43,56 @@
         assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
     }
 
-    @SmallTest
-    fun missingLookupTableReturnsNull() {
-        assertThat(FontScaleConverterFactory.forScale(3F)).isNull()
+    @LargeTest
+    @Test
+    fun missingLookupTablePastEnd_returnsLinear() {
+        val table = FontScaleConverterFactory.forScale(3F)!!
+        generateSequenceOfFractions(-10000f..10000f, step = 0.01f)
+            .map {
+                assertThat(table.convertSpToDp(it)).isWithin(CONVERSION_TOLERANCE).of(it * 3f)
+            }
+        assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(3f)
+        assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(24f)
+        assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(30f)
+        assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(15f)
+        assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
+        assertThat(table.convertSpToDp(50F)).isWithin(CONVERSION_TOLERANCE).of(150f)
+        assertThat(table.convertSpToDp(100F)).isWithin(CONVERSION_TOLERANCE).of(300f)
     }
 
     @SmallTest
-    fun missingLookupTable105ReturnsNull() {
-        assertThat(FontScaleConverterFactory.forScale(1.05F)).isNull()
+    fun missingLookupTable110_returnsInterpolated() {
+        val table = FontScaleConverterFactory.forScale(1.1F)!!
+
+        assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(1.1f)
+        assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(8f * 1.1f)
+        assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(11f)
+        assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(5f * 1.1f)
+        assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
+        assertThat(table.convertSpToDp(50F)).isLessThan(50f * 1.1f)
+        assertThat(table.convertSpToDp(100F)).isLessThan(100f * 1.1f)
+    }
+
+    @Test
+    fun missingLookupTable199_returnsInterpolated() {
+        val table = FontScaleConverterFactory.forScale(1.9999F)!!
+        assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(2f)
+        assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(16f)
+        assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(20f)
+        assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(10f)
+        assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
+    }
+
+    @Test
+    fun missingLookupTable160_returnsInterpolated() {
+        val table = FontScaleConverterFactory.forScale(1.6F)!!
+        assertThat(table.convertSpToDp(1F)).isWithin(CONVERSION_TOLERANCE).of(1f * 1.6F)
+        assertThat(table.convertSpToDp(8F)).isWithin(CONVERSION_TOLERANCE).of(8f * 1.6F)
+        assertThat(table.convertSpToDp(10F)).isWithin(CONVERSION_TOLERANCE).of(10f * 1.6F)
+        assertThat(table.convertSpToDp(20F)).isLessThan(20f * 1.6F)
+        assertThat(table.convertSpToDp(100F)).isLessThan(100f * 1.6F)
+        assertThat(table.convertSpToDp(5F)).isWithin(CONVERSION_TOLERANCE).of(5f * 1.6F)
+        assertThat(table.convertSpToDp(0F)).isWithin(CONVERSION_TOLERANCE).of(0f)
     }
 
     @SmallTest
@@ -83,7 +125,7 @@
     @Test
     fun allFeasibleScalesAndConversionsDoNotCrash() {
         generateSequenceOfFractions(-10f..10f, step = 0.01f)
-            .mapNotNull{ FontScaleConverterFactory.forScale(it) }
+            .mapNotNull{ FontScaleConverterFactory.forScale(it) }!!
             .flatMap{ table ->
                 generateSequenceOfFractions(-2000f..2000f, step = 0.01f)
                     .map{ Pair(table, it) }
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index ca1367a..0692052 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -248,17 +248,22 @@
 
     @Test
     public void testSystemDrivenInsetsAnimationLoggingListener_onReady() {
+        var loggingListener = mock(WindowInsetsAnimationControlListener.class);
+
         prepareControls();
         // only the original thread that created view hierarchy can touch its views
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            WindowInsetsAnimationControlListener loggingListener =
-                    mock(WindowInsetsAnimationControlListener.class);
             mController.setSystemDrivenInsetsAnimationLoggingListener(loggingListener);
             mController.getSourceConsumer(mImeSource).onWindowFocusGained(true);
             // since there is no focused view, forcefully make IME visible.
             mController.show(WindowInsets.Type.ime(), true /* fromIme */, null /* statsToken */);
-            verify(loggingListener).onReady(notNull(), anyInt());
+            // When using the animation thread, this must not invoke onReady()
+            mViewRoot.getView().getViewTreeObserver().dispatchOnPreDraw();
         });
+        // Wait for onReady() being dispatched on the animation thread.
+        InsetsAnimationThread.get().getThreadHandler().runWithScissors(() -> {}, 500);
+
+        verify(loggingListener).onReady(notNull(), anyInt());
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index 1db6587..6fa8f11 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -19,6 +19,7 @@
 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.captionBar;
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.navigationBars;
 
@@ -51,11 +52,13 @@
 
     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
@@ -107,6 +110,17 @@
     }
 
     @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);
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index b035c23..fde1a6d 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -248,6 +248,18 @@
     }
 
     @Test
+    public void testCalculateInsets_captionBarOffset() {
+        mState.getOrCreateSource(ID_CAPTION_BAR, captionBar())
+                .setFrame(new Rect(0, 0, 100, 300))
+                .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.getOrCreateSource(ID_STATUS_BAR, statusBars())
                 .setFrame(new Rect(0, 0, 100, 100))
diff --git a/core/tests/coretests/src/com/android/internal/os/SafeZipPathValidatorCallbackTest.java b/core/tests/coretests/src/com/android/internal/os/SafeZipPathValidatorCallbackTest.java
deleted file mode 100644
index c540a15..0000000
--- a/core/tests/coretests/src/com/android/internal/os/SafeZipPathValidatorCallbackTest.java
+++ /dev/null
@@ -1,244 +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.internal.os;
-
-import static org.junit.Assert.assertThrows;
-
-import android.compat.testing.PlatformCompatChangeRule;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
-import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.junit.runner.RunWith;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipException;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipInputStream;
-import java.util.zip.ZipOutputStream;
-
-/**
- * Test SafeZipPathCallback.
- */
-@RunWith(AndroidJUnit4.class)
-public class SafeZipPathValidatorCallbackTest {
-    @Rule
-    public TestRule mCompatChangeRule = new PlatformCompatChangeRule();
-
-    @Before
-    public void setUp() {
-        RuntimeInit.initZipPathValidatorCallback();
-    }
-
-    @Test
-    @EnableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void testNewZipFile_whenZipFileHasDangerousEntriesAndChangeEnabled_throws()
-            throws Exception {
-        final String[] dangerousEntryNames = {
-            "../foo.bar",
-            "foo/../bar.baz",
-            "foo/../../bar.baz",
-            "foo.bar/..",
-            "foo.bar/../",
-            "..",
-            "../",
-            "/foo",
-        };
-        for (String entryName : dangerousEntryNames) {
-            final File tempFile = File.createTempFile("smdc", "zip");
-            try {
-                writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
-
-                assertThrows(
-                        "ZipException expected for entry: " + entryName,
-                        ZipException.class,
-                        () -> {
-                            new ZipFile(tempFile);
-                        });
-            } finally {
-                tempFile.delete();
-            }
-        }
-    }
-
-    @Test
-    @EnableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void
-            testZipInputStreamGetNextEntry_whenZipFileHasDangerousEntriesAndChangeEnabled_throws()
-                    throws Exception {
-        final String[] dangerousEntryNames = {
-            "../foo.bar",
-            "foo/../bar.baz",
-            "foo/../../bar.baz",
-            "foo.bar/..",
-            "foo.bar/../",
-            "..",
-            "../",
-            "/foo",
-        };
-        for (String entryName : dangerousEntryNames) {
-            byte[] badZipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
-            try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(badZipBytes))) {
-                assertThrows(
-                        "ZipException expected for entry: " + entryName,
-                        ZipException.class,
-                        () -> {
-                            zis.getNextEntry();
-                        });
-            }
-        }
-    }
-
-    @Test
-    @EnableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void testNewZipFile_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow()
-            throws Exception {
-        final String[] normalEntryNames = {
-            "foo", "foo.bar", "foo..bar",
-        };
-        for (String entryName : normalEntryNames) {
-            final File tempFile = File.createTempFile("smdc", "zip");
-            try {
-                writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
-                try {
-                    new ZipFile((tempFile));
-                } catch (ZipException e) {
-                    throw new AssertionError("ZipException not expected for entry: " + entryName);
-                }
-            } finally {
-                tempFile.delete();
-            }
-        }
-    }
-
-    @Test
-    @DisableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void
-            testZipInputStreamGetNextEntry_whenZipFileHasNormalEntriesAndChangeEnabled_doesNotThrow()
-                    throws Exception {
-        final String[] normalEntryNames = {
-            "foo", "foo.bar", "foo..bar",
-        };
-        for (String entryName : normalEntryNames) {
-            byte[] zipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
-            try {
-                ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes));
-                zis.getNextEntry();
-            } catch (ZipException e) {
-                throw new AssertionError("ZipException not expected for entry: " + entryName);
-            }
-        }
-    }
-
-    @Test
-    @DisableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void
-            testNewZipFile_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow()
-                    throws Exception {
-        final String[] entryNames = {
-            "../foo.bar",
-            "foo/../bar.baz",
-            "foo/../../bar.baz",
-            "foo.bar/..",
-            "foo.bar/../",
-            "..",
-            "../",
-            "/foo",
-            "foo",
-            "foo.bar",
-            "foo..bar",
-        };
-        for (String entryName : entryNames) {
-            final File tempFile = File.createTempFile("smdc", "zip");
-            try {
-                writeZipFileOutputStreamWithEmptyEntry(tempFile, entryName);
-                try {
-                    new ZipFile((tempFile));
-                } catch (ZipException e) {
-                    throw new AssertionError("ZipException not expected for entry: " + entryName);
-                }
-            } finally {
-                tempFile.delete();
-            }
-        }
-    }
-
-    @Test
-    @DisableCompatChanges({SafeZipPathValidatorCallback.VALIDATE_ZIP_PATH_FOR_PATH_TRAVERSAL})
-    public void
-            testZipInputStreamGetNextEntry_whenZipFileHasNormalAndDangerousEntriesAndChangeDisabled_doesNotThrow()
-                    throws Exception {
-        final String[] entryNames = {
-            "../foo.bar",
-            "foo/../bar.baz",
-            "foo/../../bar.baz",
-            "foo.bar/..",
-            "foo.bar/../",
-            "..",
-            "../",
-            "/foo",
-            "foo",
-            "foo.bar",
-            "foo..bar",
-        };
-        for (String entryName : entryNames) {
-            byte[] zipBytes = getZipBytesFromZipOutputStreamWithEmptyEntry(entryName);
-            try {
-                ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes));
-                zis.getNextEntry();
-            } catch (ZipException e) {
-                throw new AssertionError("ZipException not expected for entry: " + entryName);
-            }
-        }
-    }
-
-    private void writeZipFileOutputStreamWithEmptyEntry(File tempFile, String entryName)
-            throws IOException {
-        FileOutputStream tempFileStream = new FileOutputStream(tempFile);
-        writeZipOutputStreamWithEmptyEntry(tempFileStream, entryName);
-        tempFileStream.close();
-    }
-
-    private byte[] getZipBytesFromZipOutputStreamWithEmptyEntry(String entryName)
-            throws IOException {
-        ByteArrayOutputStream bos = new ByteArrayOutputStream();
-        writeZipOutputStreamWithEmptyEntry(bos, entryName);
-        return bos.toByteArray();
-    }
-
-    private void writeZipOutputStreamWithEmptyEntry(OutputStream os, String entryName)
-            throws IOException {
-        ZipOutputStream zos = new ZipOutputStream(os);
-        ZipEntry entry = new ZipEntry(entryName);
-        zos.putNextEntry(entry);
-        zos.write(new byte[2]);
-        zos.closeEntry();
-        zos.close();
-    }
-}
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 539eb62..be2c27d 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -51,6 +51,7 @@
 import android.app.LoadedApk;
 import android.app.servertransaction.PendingTransactionActions;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -293,7 +294,7 @@
 
         private Activity launchActivity(ActivityClientRecord r) {
             return mThread.handleLaunchActivity(r, null /* pendingActions */,
-                    null /* customIntent */);
+                    Context.DEVICE_ID_DEFAULT, null /* customIntent */);
         }
 
         private void startActivity(ActivityClientRecord r) {
@@ -347,7 +348,7 @@
             doNothing().when(packageInfo).updateApplicationInfo(any(), any());
 
             return new ActivityClientRecord(mock(IBinder.class), Intent.makeMainActivity(component),
-                    0 /* ident */, info, new Configuration(), 0 /*deviceId */, null /* referrer */,
+                    0 /* ident */, info, new Configuration(), null /* referrer */,
                     null /* voiceInteractor */, null /* state */, null /* persistentState */,
                     null /* pendingResults */, null /* pendingNewIntents */,
                     null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index f3318f4..5cb5ffa0 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -471,7 +471,7 @@
         <permission name="android.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED"/>
         <!-- Permission required for CTS test - CallAudioInterceptionTest -->
         <permission name="android.permission.CALL_AUDIO_INTERCEPTION"/>
-        <!-- Permission required for CTS test - CtsPermission5TestCases -->
+        <!-- Permission required for CTS test - CtsAttributionSourceTestCases -->
         <permission name="android.permission.RENOUNCE_PERMISSIONS" />
         <permission name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
         <permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" />
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index 87a8053..0f2f879 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -767,7 +767,7 @@
      * Returns the alpha component encoded in the specified color long.
      * The returned value is always in the range \([0..1]\).
      *
-     * @param color The color long whose blue channel to extract
+     * @param color The color long whose alpha channel to extract
      * @return A float value in the range \([0..1]\)
      *
      * @see #colorSpace(long)
diff --git a/graphics/java/android/graphics/Mesh.java b/graphics/java/android/graphics/Mesh.java
index 6a1313e..66fabec 100644
--- a/graphics/java/android/graphics/Mesh.java
+++ b/graphics/java/android/graphics/Mesh.java
@@ -341,7 +341,6 @@
      * @hide so only calls from module can utilize it
      */
     long getNativeWrapperInstance() {
-        nativeUpdateMesh(mNativeMeshWrapper, mIsIndexed);
         return mNativeMeshWrapper;
     }
 
@@ -383,5 +382,4 @@
 
     private static native void nativeUpdateUniforms(long builder, String uniformName, int[] values);
 
-    private static native void nativeUpdateMesh(long nativeMeshWrapper, boolean mIsIndexed);
 }
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
index f6e3f2e..c53ddd7 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_decor_handle_menu.xml
@@ -63,38 +63,46 @@
             android:layout_width="0dp"
             android:layout_height="1dp"
             android:layout_weight="0.5" />
-        <Button
+        <ImageButton
             style="@style/CaptionWindowingButtonStyle"
             android:id="@+id/fullscreen_button"
             android:contentDescription="@string/fullscreen_text"
-            android:background="@drawable/caption_fullscreen_button"/>
+            android:src="@drawable/caption_fullscreen_button"
+            android:scaleType="fitCenter"
+            android:background="?android:selectableItemBackgroundBorderless"/>
         <Space
             android:layout_width="0dp"
             android:layout_height="1dp"
             android:layout_weight="1" />
-        <Button
+        <ImageButton
             style="@style/CaptionWindowingButtonStyle"
             android:id="@+id/split_screen_button"
             android:contentDescription="@string/split_screen_text"
-            android:background="@drawable/caption_split_screen_button"/>
+            android:src="@drawable/caption_split_screen_button"
+            android:scaleType="fitCenter"
+            android:background="?android:selectableItemBackgroundBorderless"/>
         <Space
             android:layout_width="0dp"
             android:layout_height="1dp"
             android:layout_weight="1" />
-        <Button
+        <ImageButton
             style="@style/CaptionWindowingButtonStyle"
             android:id="@+id/floating_button"
             android:contentDescription="@string/float_button_text"
-            android:background="@drawable/caption_floating_button"/>
+            android:src="@drawable/caption_floating_button"
+            android:scaleType="fitCenter"
+            android:background="?android:selectableItemBackgroundBorderless"/>
         <Space
             android:layout_width="0dp"
             android:layout_height="1dp"
             android:layout_weight="1" />
-        <Button
+        <ImageButton
             style="@style/CaptionWindowingButtonStyle"
             android:id="@+id/desktop_button"
             android:contentDescription="@string/desktop_text"
-            android:background="@drawable/caption_desktop_button"/>
+            android:src="@drawable/caption_desktop_button"
+            android:scaleType="fitCenter"
+            android:background="?android:selectableItemBackgroundBorderless"/>
         <Space
             android:layout_width="0dp"
             android:layout_height="1dp"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
index e8edad1..413cfd7 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
@@ -16,9 +16,7 @@
 <com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogLayout
     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"
-    android:background="@android:color/system_neutral1_900">
+    style="@style/LetterboxDialog">
 
     <!-- The background of the top-level layout acts as the background dim. -->
 
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
index ba9852c..5aff415 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_restart_dialog_layout.xml
@@ -16,14 +16,10 @@
 <com.android.wm.shell.compatui.RestartDialogLayout
     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"
-    android:background="@android:color/system_neutral1_900">
+    style="@style/LetterboxDialog">
 
     <!-- The background of the top-level layout acts as the background dim. -->
 
-    <!--TODO (b/266288912): Resolve overdraw warning -->
-
     <!-- Vertical margin will be set dynamically since it depends on task bounds.
          Setting the alpha of the dialog container to 0, since it shouldn't be visible until the
          enter animation starts. -->
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index 6e750a3..965ab15 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -41,6 +41,9 @@
     <color name="letterbox_education_accent_primary">@android:color/system_accent1_100</color>
     <color name="letterbox_education_text_secondary">@android:color/system_neutral2_200</color>
 
+    <!-- Letterbox Dialog -->
+    <color name="letterbox_dialog_background">@android:color/system_neutral1_900</color>
+
     <!-- GM2 colors -->
     <color name="GM2_grey_200">#E8EAED</color>
     <color name="GM2_grey_700">#5F6368</color>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index 0a0c49f..bc2e71d 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -38,11 +38,9 @@
     </style>
 
     <style name="CaptionWindowingButtonStyle">
-        <item name="android:layout_width">32dp</item>
-        <item name="android:layout_height">32dp</item>
+        <item name="android:layout_width">40dp</item>
+        <item name="android:layout_height">40dp</item>
         <item name="android:padding">4dp</item>
-        <item name="android:layout_marginTop">5dp</item>
-        <item name="android:layout_marginBottom">5dp</item>
     </style>
 
     <style name="CaptionMenuButtonStyle" parent="@style/Widget.AppCompat.Button.Borderless">
@@ -80,6 +78,12 @@
         <item name="android:textColor">@color/tv_pip_edu_text</item>
     </style>
 
+    <style name="LetterboxDialog" parent="@android:style/Theme.Holo">
+        <item name="android:layout_width">wrap_content</item>
+        <item name="android:layout_height">wrap_content</item>
+        <item name="android:background">@color/letterbox_dialog_background</item>
+    </style>
+
     <style name="RestartDialogTitleText">
         <item name="android:textSize">24sp</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index b6fd0bb..585f81c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -428,9 +428,9 @@
     }
 
     @Override
-    public void addStartingWindow(StartingWindowInfo info) {
+    public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
         if (mStartingWindow != null) {
-            mStartingWindow.addStartingWindow(info);
+            mStartingWindow.addStartingWindow(info, appToken);
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java
index 04bff97..306d619 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java
@@ -32,6 +32,7 @@
 import android.window.WindowContainerTransaction;
 
 import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.ArrayList;
 
@@ -115,7 +116,7 @@
             boolean latest) {
         for (int i = mPending.size() - 1; i >= 0; --i) {
             if (mPending.get(i).mTaskView != taskView) continue;
-            if (Transitions.isClosingType(mPending.get(i).mType) == closing) {
+            if (TransitionUtil.isClosingType(mPending.get(i).mType) == closing) {
                 return mPending.get(i);
             }
             if (latest) {
@@ -148,7 +149,7 @@
         final TaskViewTaskController taskView = findTaskView(triggerTask);
         if (taskView == null) return null;
         // Opening types should all be initiated by shell
-        if (!Transitions.isClosingType(request.getType())) return null;
+        if (!TransitionUtil.isClosingType(request.getType())) return null;
         PendingTransition pending = findPending(taskView, true /* closing */, false /* latest */);
         if (pending == null) {
             pending = new PendingTransition(request.getType(), null, taskView, null /* cookie */);
@@ -238,7 +239,7 @@
         for (int i = 0; i < info.getChanges().size(); ++i) {
             final TransitionInfo.Change chg = info.getChanges().get(i);
             if (chg.getTaskInfo() == null) continue;
-            if (Transitions.isClosingType(chg.getMode())) {
+            if (TransitionUtil.isClosingType(chg.getMode())) {
                 final boolean isHide = chg.getMode() == TRANSIT_TO_BACK;
                 TaskViewTaskController tv = findTaskView(chg.getTaskInfo());
                 if (tv == null) {
@@ -255,7 +256,7 @@
                     tv.prepareCloseAnimation();
                 }
                 changesHandled++;
-            } else if (Transitions.isOpeningType(chg.getMode())) {
+            } else if (TransitionUtil.isOpeningType(chg.getMode())) {
                 final boolean taskIsNew = chg.getMode() == TRANSIT_OPEN;
                 final TaskViewTaskController tv;
                 if (taskIsNew) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
index 579f7aa..c767376 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
@@ -29,7 +29,7 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
 
 /**
  * Wrapper to handle the ActivityEmbedding animation update in one
@@ -90,7 +90,7 @@
         mChange = change;
         mLeash = leash;
         mWholeAnimationBounds.set(wholeAnimationBounds);
-        if (Transitions.isClosingType(change.getMode())) {
+        if (TransitionUtil.isClosingType(change.getMode())) {
             // When it is closing, we want to show the content at the start position in case the
             // window is resizing as well. For example, when the activities is changing from split
             // to stack, the bottom TaskFragment will be resized to fullscreen when hiding.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
index fe3c4ea..1df6ecd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
@@ -43,7 +43,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.wm.shell.common.ScreenshotUtils;
-import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -184,7 +184,7 @@
         if (isChangeTransition) {
             return createChangeAnimationAdapters(info, startTransaction);
         }
-        if (Transitions.isClosingType(info.getType())) {
+        if (TransitionUtil.isClosingType(info.getType())) {
             return createCloseAnimationAdapters(info);
         }
         return createOpenAnimationAdapters(info);
@@ -219,7 +219,7 @@
         final Rect openingWholeScreenBounds = new Rect();
         final Rect closingWholeScreenBounds = new Rect();
         for (TransitionInfo.Change change : info.getChanges()) {
-            if (Transitions.isOpeningType(change.getMode())) {
+            if (TransitionUtil.isOpeningType(change.getMode())) {
                 openingChanges.add(change);
                 openingWholeScreenBounds.union(change.getEndAbsBounds());
             } else {
@@ -271,7 +271,7 @@
                 continue;
             }
             final TransitionInfo.Change change = adapter.mChange;
-            if (Transitions.isOpeningType(adapter.mChange.getMode())) {
+            if (TransitionUtil.isOpeningType(adapter.mChange.getMode())) {
                 // Need to screenshot after startTransaction is applied otherwise activity
                 // may not be visible or ready yet.
                 postStartTransactionCallbacks.add(
@@ -343,7 +343,7 @@
                 // When the parent window is also included in the transition as an opening window,
                 // we would like to animate the parent window instead.
                 final TransitionInfo.Change parentChange = info.getChange(parentToken);
-                if (parentChange != null && Transitions.isOpeningType(parentChange.getMode())) {
+                if (parentChange != null && TransitionUtil.isOpeningType(parentChange.getMode())) {
                     // We won't create a separate animation for the parent, but to animate the
                     // parent for the child resizing.
                     handledChanges.add(parentChange);
@@ -404,7 +404,7 @@
                 // No-op if it will be covered by the changing parent window, or it is a changing
                 // window without bounds change.
                 animation = ActivityEmbeddingAnimationSpec.createNoopAnimation(change);
-            } else if (Transitions.isClosingType(change.getMode())) {
+            } else if (TransitionUtil.isClosingType(change.getMode())) {
                 animation = mAnimationSpec.createChangeBoundsCloseAnimation(change, parentBounds);
                 shouldShouldBackgroundColor = false;
             } else {
@@ -469,7 +469,7 @@
                 // When the parent window is also included in the transition as an opening window,
                 // we would like to animate the parent window instead.
                 final TransitionInfo.Change parentChange = info.getChange(parentToken);
-                if (parentChange != null && Transitions.isOpeningType(parentChange.getMode())) {
+                if (parentChange != null && TransitionUtil.isOpeningType(parentChange.getMode())) {
                     changingChanges.add(parentChange);
                 }
             }
@@ -491,8 +491,8 @@
                 // No-op if it will be covered by the changing parent window.
                 continue;
             }
-            hasOpeningWindow |= Transitions.isOpeningType(change.getMode());
-            hasClosingWindow |= Transitions.isClosingType(change.getMode());
+            hasOpeningWindow |= TransitionUtil.isOpeningType(change.getMode());
+            hasClosingWindow |= TransitionUtil.isClosingType(change.getMode());
         }
         return hasOpeningWindow && hasClosingWindow;
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
index d10a674..cb8342a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
@@ -36,7 +36,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.internal.policy.TransitionAnimation;
-import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
 
 /** Animation spec for ActivityEmbedding transition. */
 // TODO(b/206557124): provide an easier way to customize animation
@@ -73,7 +73,7 @@
     @NonNull
     static Animation createNoopAnimation(@NonNull TransitionInfo.Change change) {
         // Noop but just keep the window showing/hiding.
-        final float alpha = Transitions.isClosingType(change.getMode()) ? 0f : 1f;
+        final float alpha = TransitionUtil.isClosingType(change.getMode()) ? 0f : 1f;
         return new AlphaAnimation(alpha, alpha);
     }
 
@@ -198,7 +198,7 @@
     @NonNull
     Animation loadOpenAnimation(@NonNull TransitionInfo info,
             @NonNull TransitionInfo.Change change, @NonNull Rect wholeAnimationBounds) {
-        final boolean isEnter = Transitions.isOpeningType(change.getMode());
+        final boolean isEnter = TransitionUtil.isOpeningType(change.getMode());
         final Animation animation;
         if (shouldShowBackdrop(info, change)) {
             animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
@@ -222,7 +222,7 @@
     @NonNull
     Animation loadCloseAnimation(@NonNull TransitionInfo info,
             @NonNull TransitionInfo.Change change, @NonNull Rect wholeAnimationBounds) {
-        final boolean isEnter = Transitions.isOpeningType(change.getMode());
+        final boolean isEnter = TransitionUtil.isOpeningType(change.getMode());
         final Animation animation;
         if (shouldShowBackdrop(info, change)) {
             animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
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 713dd39..69f0bad 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
@@ -371,7 +371,14 @@
         mViewHost.relayout(lp);
     }
 
-    void setInteractive(boolean interactive, String from) {
+    /**
+     * Set divider should interactive to user or not.
+     *
+     * @param interactive divider interactive.
+     * @param hideHandle divider handle hidden or not, only work when interactive is false.
+     * @param from caller from where.
+     */
+    void setInteractive(boolean interactive, boolean hideHandle, String from) {
         if (interactive == mInteractive) return;
         ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
                 "Set divider bar %s from %s", interactive ? "interactive" : "non-interactive",
@@ -387,7 +394,7 @@
             mMoving = false;
         }
         releaseTouching();
-        mHandle.setVisibility(mInteractive ? View.VISIBLE : View.INVISIBLE);
+        mHandle.setVisibility(!mInteractive && hideHandle ? View.INVISIBLE : View.VISIBLE);
     }
 
     private boolean isLandscape() {
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 8a18271..7ac4d51 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
@@ -486,6 +486,17 @@
     }
 
     /**
+     * Set divider should interactive to user or not.
+     *
+     * @param interactive divider interactive.
+     * @param hideHandle divider handle hidden or not, only work when interactive is false.
+     * @param from caller from where.
+     */
+    public void setDividerInteractive(boolean interactive, boolean hideHandle, String from) {
+        mSplitWindowManager.setInteractive(interactive, hideHandle, from);
+    }
+
+    /**
      * Sets new divide position and updates bounds correspondingly. Notifies listener if the new
      * target indicates dismissing split.
      */
@@ -735,21 +746,28 @@
         }
     }
 
-    /** Apply recorded task layout to the {@link WindowContainerTransaction}. */
-    public void applyTaskChanges(WindowContainerTransaction wct,
+    /** Apply recorded task layout to the {@link WindowContainerTransaction}.
+     *
+     * @return true if stage bounds actually update.
+     */
+    public boolean applyTaskChanges(WindowContainerTransaction wct,
             ActivityManager.RunningTaskInfo task1, ActivityManager.RunningTaskInfo task2) {
+        boolean boundsChanged = false;
         if (!mBounds1.equals(mWinBounds1) || !task1.token.equals(mWinToken1)) {
             wct.setBounds(task1.token, mBounds1);
             wct.setSmallestScreenWidthDp(task1.token, getSmallestWidthDp(mBounds1));
             mWinBounds1.set(mBounds1);
             mWinToken1 = task1.token;
+            boundsChanged = true;
         }
         if (!mBounds2.equals(mWinBounds2) || !task2.token.equals(mWinToken2)) {
             wct.setBounds(task2.token, mBounds2);
             wct.setSmallestScreenWidthDp(task2.token, getSmallestWidthDp(mBounds2));
             mWinBounds2.set(mBounds2);
             mWinToken2 = task2.token;
+            boundsChanged = true;
         }
+        return boundsChanged;
     }
 
     private int getSmallestWidthDp(Rect bounds) {
@@ -1091,7 +1109,7 @@
             // ImePositionProcessor#onImeVisibilityChanged directly in DividerView is not enough
             // because DividerView won't receive onImeVisibilityChanged callback after it being
             // re-inflated.
-            mSplitWindowManager.setInteractive(!mImeShown || !mHasImeFocus || isFloating,
+            setDividerInteractive(!mImeShown || !mHasImeFocus || isFloating, true,
                     "onImeStartPositioning");
 
             return needOffset ? IME_ANIMATION_NO_ALPHA : 0;
@@ -1118,7 +1136,7 @@
             // Restore the split layout when wm-shell is not controlling IME insets anymore.
             if (!controlling && mImeShown) {
                 reset();
-                mSplitWindowManager.setInteractive(true, "onImeControlTargetChanged");
+                setDividerInteractive(true, true, "onImeControlTargetChanged");
                 mSplitLayoutHandler.setLayoutOffsetTarget(0, 0, SplitLayout.this);
                 mSplitLayoutHandler.onLayoutPositionChanging(SplitLayout.this);
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index eb3c1df..00361d9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -168,9 +168,16 @@
         }
     }
 
-    void setInteractive(boolean interactive, String from) {
+    /**
+     * Set divider should interactive to user or not.
+     *
+     * @param interactive divider interactive.
+     * @param hideHandle divider handle hidden or not, only work when interactive is false.
+     * @param from caller from where.
+     */
+    void setInteractive(boolean interactive, boolean hideHandle, String from) {
         if (mDividerView == null) return;
-        mDividerView.setInteractive(interactive, from);
+        mDividerView.setInteractive(interactive, hideHandle, from);
     }
 
     View getDividerView() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 3b2db51..76d9152 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -126,14 +126,12 @@
     private final Lazy<Transitions> mTransitionsLazy;
     private final DockStateReader mDockStateReader;
     private final CompatUIConfiguration mCompatUIConfiguration;
-
-    private CompatUICallback mCallback;
-
     // Only show each hint once automatically in the process life.
     private final CompatUIHintsState mCompatUIHintsState;
-
     private final CompatUIShellCommandHandler mCompatUIShellCommandHandler;
 
+    private CompatUICallback mCallback;
+
     // Indicates if the keyguard is currently showing, in which case compat UIs shouldn't
     // be shown.
     private boolean mKeyguardShowing;
@@ -372,19 +370,20 @@
         RestartDialogWindowManager layout =
                 mTaskIdToRestartDialogWindowManagerMap.get(taskInfo.taskId);
         if (layout != null) {
-            // TODO(b/266262111) Handle theme change when taskListener changes
-            if (layout.getTaskListener() != taskListener) {
-                mSetOfTaskIdsShowingRestartDialog.remove(taskInfo.taskId);
-            }
-            layout.setRequestRestartDialog(
-                    mSetOfTaskIdsShowingRestartDialog.contains(taskInfo.taskId));
-            // UI already exists, update the UI layout.
-            if (!layout.updateCompatInfo(taskInfo, taskListener,
-                    showOnDisplay(layout.getDisplayId()))) {
-                // The layout is no longer eligible to be shown, remove from active layouts.
+            if (layout.needsToBeRecreated(taskInfo, taskListener)) {
                 mTaskIdToRestartDialogWindowManagerMap.remove(taskInfo.taskId);
+                layout.release();
+            } else {
+                layout.setRequestRestartDialog(
+                        mSetOfTaskIdsShowingRestartDialog.contains(taskInfo.taskId));
+                // UI already exists, update the UI layout.
+                if (!layout.updateCompatInfo(taskInfo, taskListener,
+                        showOnDisplay(layout.getDisplayId()))) {
+                    // The layout is no longer eligible to be shown, remove from active layouts.
+                    mTaskIdToRestartDialogWindowManagerMap.remove(taskInfo.taskId);
+                }
+                return;
             }
-            return;
         }
         // Create a new UI layout.
         final Context context = getOrCreateDisplayContext(taskInfo.displayId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
index efd4594..b22c9c7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIWindowManagerAbstract.java
@@ -151,7 +151,6 @@
     @Override
     public void setConfiguration(Configuration configuration) {
         super.setConfiguration(configuration);
-        // TODO(b/266262111): Investigate loss of theme configuration when switching TaskListener
         mContext = mContext.createConfigurationContext(configuration);
     }
 
@@ -210,7 +209,8 @@
         }
 
         View layout = getLayout();
-        if (layout == null || prevTaskListener != taskListener) {
+        if (layout == null || prevTaskListener != taskListener
+                || mTaskConfig.uiMode != prevTaskConfig.uiMode) {
             // Layout wasn't created yet or TaskListener changed, recreate the layout for new
             // surface parent.
             release();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
index 10f25d0..2440838 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/RestartDialogWindowManager.java
@@ -155,6 +155,11 @@
         return super.updateCompatInfo(taskInfo, taskListener, canShow);
     }
 
+    boolean needsToBeRecreated(TaskInfo taskInfo, ShellTaskOrganizer.TaskListener taskListener) {
+        return taskInfo.configuration.uiMode != mTaskInfo.configuration.uiMode
+                || !getTaskListener().equals(taskListener);
+    }
+
     private void updateDialogMargins() {
         if (mLayout == null) {
             return;
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 d1f4398..948bf2d 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
@@ -196,7 +196,8 @@
             DisplayController displayController,
             SyncTransactionQueue syncQueue,
             Optional<DesktopModeController> desktopModeController,
-            Optional<DesktopTasksController> desktopTasksController) {
+            Optional<DesktopTasksController> desktopTasksController,
+            Optional<SplitScreenController> splitScreenController) {
         if (DesktopModeStatus.isAnyEnabled()) {
             return new DesktopModeWindowDecorViewModel(
                     context,
@@ -206,7 +207,8 @@
                     displayController,
                     syncQueue,
                     desktopModeController,
-                    desktopTasksController);
+                    desktopTasksController,
+                    splitScreenController);
         }
         return new CaptionWindowDecorViewModel(
                     context,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index b59fe18..4cfaae6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -36,6 +36,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 
 import android.content.ClipDescription;
+import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.PixelFormat;
@@ -58,9 +59,9 @@
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.annotations.ExternalMainThread;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.sysui.ConfigurationChangeListener;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
 
@@ -70,7 +71,7 @@
  * Handles the global drag and drop handling for the Shell.
  */
 public class DragAndDropController implements DisplayController.OnDisplaysChangedListener,
-        View.OnDragListener, ConfigurationChangeListener {
+        View.OnDragListener, ComponentCallbacks2 {
 
     private static final String TAG = DragAndDropController.class.getSimpleName();
 
@@ -119,7 +120,6 @@
         mMainExecutor.executeDelayed(() -> {
             mDisplayController.addDisplayWindowListener(this);
         }, 0);
-        mShellController.addConfigurationChangeListener(this);
     }
 
     /**
@@ -180,6 +180,7 @@
         try {
             wm.addView(rootView, layoutParams);
             addDisplayDropTarget(displayId, context, wm, rootView, dragLayout);
+            context.registerComponentCallbacks(this);
         } catch (WindowManager.InvalidDisplayException e) {
             Slog.w(TAG, "Unable to add view for display id: " + displayId);
         }
@@ -209,6 +210,7 @@
         if (pd == null) {
             return;
         }
+        pd.context.unregisterComponentCallbacks(this);
         pd.wm.removeViewImmediate(pd.rootView);
         mDisplayDropTargets.remove(displayId);
     }
@@ -328,18 +330,29 @@
         return mimeTypes;
     }
 
-    @Override
-    public void onThemeChanged() {
-        for (int i = 0; i < mDisplayDropTargets.size(); i++) {
-            mDisplayDropTargets.get(i).dragLayout.onThemeChange();
-        }
-    }
-
+    // Note: Component callbacks are always called on the main thread of the process
+    @ExternalMainThread
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
-        for (int i = 0; i < mDisplayDropTargets.size(); i++) {
-            mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
-        }
+        mMainExecutor.execute(() -> {
+            for (int i = 0; i < mDisplayDropTargets.size(); i++) {
+                mDisplayDropTargets.get(i).dragLayout.onConfigChanged(newConfig);
+            }
+        });
+    }
+
+    // Note: Component callbacks are always called on the main thread of the process
+    @ExternalMainThread
+    @Override
+    public void onTrimMemory(int level) {
+        // Do nothing
+    }
+
+    // Note: Component callbacks are always called on the main thread of the process
+    @ExternalMainThread
+    @Override
+    public void onLowMemory() {
+        // Do nothing
     }
 
     private static class PerDisplay {
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 44fd8ee..fe42822a 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
@@ -18,6 +18,8 @@
 
 import static android.app.StatusBarManager.DISABLE_NONE;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.content.pm.ActivityInfo.CONFIG_ASSETS_PATHS;
+import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -72,6 +74,7 @@
     private final SplitScreenController mSplitScreenController;
     private final IconProvider mIconProvider;
     private final StatusBarManager mStatusBarManager;
+    private final Configuration mLastConfiguration = new Configuration();
 
     private DragAndDropPolicy.Target mCurrentTarget = null;
     private DropZoneView mDropZoneView1;
@@ -92,6 +95,7 @@
         mIconProvider = iconProvider;
         mPolicy = new DragAndDropPolicy(context, splitScreenController);
         mStatusBarManager = context.getSystemService(StatusBarManager.class);
+        mLastConfiguration.setTo(context.getResources().getConfiguration());
 
         mDisplayMargin = context.getResources().getDimensionPixelSize(
                 R.dimen.drop_layout_display_margin);
@@ -132,11 +136,6 @@
         return super.onApplyWindowInsets(insets);
     }
 
-    public void onThemeChange() {
-        mDropZoneView1.onThemeChange();
-        mDropZoneView2.onThemeChange();
-    }
-
     public void onConfigChanged(Configuration newConfig) {
         if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE
                 && getOrientation() != HORIZONTAL) {
@@ -147,6 +146,15 @@
             setOrientation(LinearLayout.VERTICAL);
             updateContainerMargins(newConfig.orientation);
         }
+
+        final int diff = newConfig.diff(mLastConfiguration);
+        final boolean themeChanged = (diff & CONFIG_ASSETS_PATHS) != 0
+                || (diff & CONFIG_UI_MODE) != 0;
+        if (themeChanged) {
+            mDropZoneView1.onThemeChange();
+            mDropZoneView2.onThemeChange();
+        }
+        mLastConfiguration.setTo(newConfig);
     }
 
     private void updateContainerMarginsForSingleTask() {
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 e5c0570..6b0337d 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
@@ -40,7 +40,6 @@
 import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP;
 import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP_TO_SPLIT;
 import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP;
-import static com.android.wm.shell.transition.Transitions.isOpeningType;
 
 import android.animation.Animator;
 import android.app.ActivityManager;
@@ -72,6 +71,7 @@
 import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.transition.CounterRotatorHelper;
 import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.Optional;
 
@@ -702,7 +702,7 @@
         for (int i = info.getChanges().size() - 1; i >= 0; --i) {
             final TransitionInfo.Change change = info.getChanges().get(i);
             if (change == enterPip) continue;
-            if (isOpeningType(change.getMode())) {
+            if (TransitionUtil.isOpeningType(change.getMode())) {
                 final SurfaceControl leash = change.getLeash();
                 startTransaction.show(leash).setAlpha(leash, 1.f);
             }
@@ -873,7 +873,7 @@
                 continue;
             }
 
-            if (isOpeningType(mode) && change.getParent() == null) {
+            if (TransitionUtil.isOpeningType(mode) && change.getParent() == null) {
                 final SurfaceControl leash = change.getLeash();
                 final Rect endBounds = change.getEndAbsBounds();
                 startTransaction
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 c7ad4fd..94b9e90 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
@@ -422,6 +422,11 @@
         mStageCoordinator.goToFullscreenFromSplit();
     }
 
+    /** Move the specified task to fullscreen, regardless of focus state. */
+    public void moveTaskToFullscreen(int taskId) {
+        mStageCoordinator.moveTaskToFullscreen(taskId);
+    }
+
     public boolean isLaunchToSplit(TaskInfo taskInfo) {
         return mStageCoordinator.isLaunchToSplit(taskInfo);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 520da92..e1c0895 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -53,6 +53,7 @@
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.transition.OneShotRemoteHandler;
 import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.ArrayList;
 
@@ -339,6 +340,12 @@
     IBinder startResizeTransition(WindowContainerTransaction wct,
             Transitions.TransitionHandler handler,
             @Nullable TransitionFinishedCallback finishCallback) {
+        if (mPendingResize != null) {
+            mPendingResize.cancel(null);
+            mAnimations.clear();
+            onFinish(null /* wct */, null /* wctCB */);
+        }
+
         IBinder transition = mTransitions.startTransition(TRANSIT_CHANGE, wct, handler);
         setResizeTransition(transition, finishCallback);
         return transition;
@@ -531,7 +538,7 @@
     }
 
     private boolean isOpeningTransition(TransitionInfo info) {
-        return Transitions.isOpeningType(info.getType())
+        return TransitionUtil.isOpeningType(info.getType())
                 || info.getType() == TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE
                 || info.getType() == TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
     }
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 7833cfe..3ed5ec5 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
@@ -61,8 +61,8 @@
 import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
 import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE;
 import static com.android.wm.shell.transition.Transitions.TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
-import static com.android.wm.shell.transition.Transitions.isClosingType;
-import static com.android.wm.shell.transition.Transitions.isOpeningType;
+import static com.android.wm.shell.util.TransitionUtil.isClosingType;
+import static com.android.wm.shell.util.TransitionUtil.isOpeningType;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -135,6 +135,7 @@
 import com.android.wm.shell.transition.LegacyTransitions;
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.util.SplitBounds;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -204,7 +205,7 @@
     // and exit, since exit itself can trigger a number of changes that update the stages.
     private boolean mShouldUpdateRecents;
     private boolean mExitSplitScreenOnHide;
-    private boolean mIsSplitEntering;
+    private boolean mIsDividerRemoteAnimating;
     private boolean mIsDropEntering;
     private boolean mIsExiting;
 
@@ -881,7 +882,7 @@
 
         // Set false to avoid record new bounds with old task still on top;
         mShouldUpdateRecents = false;
-        mIsSplitEntering = true;
+        mIsDividerRemoteAnimating = true;
         if (mSplitRequest == null) {
             mSplitRequest = new SplitRequest(mainTaskId,
                     mainPendingIntent != null ? mainPendingIntent.getIntent() : null,
@@ -936,7 +937,7 @@
                         new IRemoteAnimationFinishedCallback.Stub() {
                             @Override
                             public void onAnimationFinished() throws RemoteException {
-                                onRemoteAnimationFinishedOrCancelled(false /* cancel */, evictWct);
+                                onRemoteAnimationFinishedOrCancelled(evictWct);
                                 finishedCallback.onAnimationFinished();
                             }
                         };
@@ -952,7 +953,7 @@
 
             @Override
             public void onAnimationCancelled(boolean isKeyguardOccluded) {
-                onRemoteAnimationFinishedOrCancelled(true /* cancel */, evictWct);
+                onRemoteAnimationFinishedOrCancelled(evictWct);
                 try {
                     adapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
                 } catch (RemoteException e) {
@@ -973,15 +974,14 @@
         }
     }
 
-    private void onRemoteAnimationFinishedOrCancelled(boolean cancel,
-            WindowContainerTransaction evictWct) {
-        mIsSplitEntering = false;
+    private void onRemoteAnimationFinishedOrCancelled(WindowContainerTransaction evictWct) {
+        mIsDividerRemoteAnimating = false;
         mShouldUpdateRecents = true;
         mSplitRequest = null;
         // If any stage has no child after animation finished, it means that split will display
         // nothing, such status will happen if task and intent is same app but not support
         // multi-instance, we should exit split and expand that app as full screen.
-        if (!cancel && (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0)) {
+        if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
             mMainExecutor.execute(() ->
                     exitSplitScreen(mMainStage.getChildCount() == 0
                             ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
@@ -1236,12 +1236,12 @@
             // Notify recents if we are exiting in a way that breaks the pair, and disable further
             // updates to splits in the recents until we enter split again
             if (shouldBreakPairedTaskInRecents(exitReason) && mShouldUpdateRecents) {
-                recentTasks.removeSplitPair(mMainStage.getLastVisibleTaskId());
-                recentTasks.removeSplitPair(mSideStage.getLastVisibleTaskId());
+                recentTasks.removeSplitPair(mMainStage.getTopVisibleChildTaskId());
+                recentTasks.removeSplitPair(mSideStage.getTopVisibleChildTaskId());
             }
         });
         mShouldUpdateRecents = false;
-        mIsSplitEntering = false;
+        mIsDividerRemoteAnimating = false;
 
         mSplitLayout.getInvisibleBounds(mTempRect1);
         if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) {
@@ -1584,7 +1584,7 @@
                 && !ENABLE_SHELL_TRANSITIONS) {
             // Clear the divider remote animating flag as the divider will be re-rendered to apply
             // the new rotation config.
-            mIsSplitEntering = false;
+            mIsDividerRemoteAnimating = false;
             mSplitLayout.update(null /* t */);
             onLayoutSizeChanged(mSplitLayout);
         }
@@ -1634,9 +1634,9 @@
     }
 
     void onChildTaskAppeared(StageListenerImpl stageListener, int taskId) {
-        if (stageListener == mSideStageListener && !isSplitScreenVisible() && isSplitActive()
-                && !mIsSplitEntering) {
-            // Handle entring split case here if split already running background.
+        // Handle entering split screen while there is a split pair running in the background.
+        if (stageListener == mSideStageListener && !isSplitScreenVisible()
+                && mSplitRequest == null) {
             if (mIsDropEntering) {
                 mSplitLayout.resetDividerPosition();
             } else {
@@ -1728,7 +1728,7 @@
         mDividerVisible = visible;
         sendSplitVisibilityChanged();
 
-        if (mIsSplitEntering) {
+        if (mIsDividerRemoteAnimating) {
             ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
                     "   Skip animating divider bar due to it's remote animating.");
             return;
@@ -1748,7 +1748,7 @@
                     "   Skip animating divider bar due to divider leash not ready.");
             return;
         }
-        if (mIsSplitEntering) {
+        if (mIsDividerRemoteAnimating) {
             ProtoLog.d(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN,
                     "   Skip animating divider bar due to it's remote animating.");
             return;
@@ -1816,7 +1816,8 @@
                 mSplitLayout.flingDividerToDismiss(
                         mSideStagePosition != SPLIT_POSITION_BOTTOM_OR_RIGHT,
                         EXIT_REASON_APP_FINISHED);
-            } else if (!isSplitScreenVisible() && !mIsSplitEntering) {
+            } else if (!isSplitScreenVisible() && mSplitRequest == null) {
+                // Dismiss split screen in the background once any sides of the split become empty.
                 exitSplitScreen(null /* childrenToTop */, EXIT_REASON_APP_FINISHED);
             }
         } else if (isSideStage && hasChildren && !mMainStage.isActive()) {
@@ -1924,10 +1925,14 @@
         }
 
         final WindowContainerTransaction wct = new WindowContainerTransaction();
-        updateWindowBounds(layout, wct);
+        boolean sizeChanged = updateWindowBounds(layout, wct);
+        if (!sizeChanged) return;
+
         sendOnBoundsChanged();
         if (ENABLE_SHELL_TRANSITIONS) {
-            mSplitTransitions.startResizeTransition(wct, this, null /* callback */);
+            mSplitLayout.setDividerInteractive(false, false, "onSplitResizeStart");
+            mSplitTransitions.startResizeTransition(wct, this, (finishWct, t) ->
+                    mSplitLayout.setDividerInteractive(true, false, "onSplitResizeFinish"));
         } else {
             mSyncQueue.queue(wct);
             mSyncQueue.runInSync(t -> {
@@ -1946,13 +1951,16 @@
     /**
      * Populates `wct` with operations that match the split windows to the current layout.
      * To match relevant surfaces, make sure to call updateSurfaceBounds after `wct` is applied
+     *
+     * @return true if stage bounds actually .
      */
-    private void updateWindowBounds(SplitLayout layout, WindowContainerTransaction wct) {
+    private boolean updateWindowBounds(SplitLayout layout, WindowContainerTransaction wct) {
         final StageTaskListener topLeftStage =
                 mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mSideStage : mMainStage;
         final StageTaskListener bottomRightStage =
                 mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? mMainStage : mSideStage;
-        layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo, bottomRightStage.mRootTaskInfo);
+        return layout.applyTaskChanges(wct, topLeftStage.mRootTaskInfo,
+                bottomRightStage.mRootTaskInfo);
     }
 
     void updateSurfaceBounds(@Nullable SplitLayout layout, @NonNull SurfaceControl.Transaction t,
@@ -2271,7 +2279,7 @@
 
             // Use normal animations.
             return false;
-        } else if (mMixedHandler != null && Transitions.hasDisplayChange(info)) {
+        } else if (mMixedHandler != null && TransitionUtil.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,
@@ -2399,6 +2407,20 @@
         mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
     }
 
+    /** Move the specified task to fullscreen, regardless of focus state. */
+    public void moveTaskToFullscreen(int taskId) {
+        boolean leftOrTop;
+        if (mMainStage.containsTask(taskId)) {
+            leftOrTop = (mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
+        } else if (mSideStage.containsTask(taskId)) {
+            leftOrTop = (mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT);
+        } else {
+            return;
+        }
+        mSplitLayout.flingDividerToDismiss(!leftOrTop, EXIT_REASON_FULLSCREEN_SHORTCUT);
+
+    }
+
     boolean isLaunchToSplit(TaskInfo taskInfo) {
         return getActivateSplitPosition(taskInfo) != SPLIT_POSITION_UNDEFINED;
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 0359761..a841b7f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -92,7 +92,6 @@
     protected SurfaceControl mDimLayer;
     protected SparseArray<ActivityManager.RunningTaskInfo> mChildrenTaskInfo = new SparseArray<>();
     private final SparseArray<SurfaceControl> mChildrenLeashes = new SparseArray<>();
-    private int mLastVisibleTaskId = INVALID_TASK_ID;
     // TODO(b/204308910): Extracts SplitDecorManager related code to common package.
     private SplitDecorManager mSplitDecorManager;
 
@@ -124,13 +123,6 @@
     }
 
     /**
-     * Returns the last visible task's id.
-     */
-    int getLastVisibleTaskId() {
-        return mLastVisibleTaskId;
-    }
-
-    /**
      * Returns the top visible child task's id.
      */
     int getTopVisibleChildTaskId() {
@@ -229,9 +221,6 @@
                 return;
             }
             mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
-            if (taskInfo.isVisible && taskInfo.taskId != mLastVisibleTaskId) {
-                mLastVisibleTaskId = taskInfo.taskId;
-            }
             mCallbacks.onChildTaskStatusChanged(taskInfo.taskId, true /* present */,
                     taskInfo.isVisible);
             if (!ENABLE_SHELL_TRANSITIONS) {
@@ -264,9 +253,6 @@
         } else if (mChildrenTaskInfo.contains(taskId)) {
             mChildrenTaskInfo.remove(taskId);
             mChildrenLeashes.remove(taskId);
-            if (taskId == mLastVisibleTaskId) {
-                mLastVisibleTaskId = INVALID_TASK_ID;
-            }
             mCallbacks.onChildTaskStatusChanged(taskId, false /* present */, taskInfo.isVisible);
             if (ENABLE_SHELL_TRANSITIONS) {
                 // Status is managed/synchronized by the transition lifecycle.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/AbsSplashWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/AbsSplashWindowCreator.java
deleted file mode 100644
index 1ddd8f9..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/AbsSplashWindowCreator.java
+++ /dev/null
@@ -1,67 +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.startingsurface;
-
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.hardware.display.DisplayManager;
-import android.view.Display;
-
-import com.android.wm.shell.common.ShellExecutor;
-
-// abstract class to create splash screen window(or windowless window)
-abstract class AbsSplashWindowCreator {
-    protected static final String TAG = StartingWindowController.TAG;
-    protected final SplashscreenContentDrawer mSplashscreenContentDrawer;
-    protected final Context mContext;
-    protected final DisplayManager mDisplayManager;
-    protected final ShellExecutor mSplashScreenExecutor;
-    protected final StartingSurfaceDrawer.StartingWindowRecordManager mStartingWindowRecordManager;
-
-    private StartingSurface.SysuiProxy mSysuiProxy;
-
-    AbsSplashWindowCreator(SplashscreenContentDrawer contentDrawer, Context context,
-            ShellExecutor splashScreenExecutor, DisplayManager displayManager,
-            StartingSurfaceDrawer.StartingWindowRecordManager startingWindowRecordManager) {
-        mSplashscreenContentDrawer = contentDrawer;
-        mContext = context;
-        mSplashScreenExecutor = splashScreenExecutor;
-        mDisplayManager = displayManager;
-        mStartingWindowRecordManager = startingWindowRecordManager;
-    }
-
-    int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) {
-        return splashScreenThemeResId != 0
-                ? splashScreenThemeResId
-                : activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource()
-                        : com.android.internal.R.style.Theme_DeviceDefault_DayNight;
-    }
-
-    protected Display getDisplay(int displayId) {
-        return mDisplayManager.getDisplay(displayId);
-    }
-
-    void setSysuiProxy(StartingSurface.SysuiProxy sysuiProxy) {
-        mSysuiProxy = sysuiProxy;
-    }
-
-    protected void requestTopUi(boolean requestTopUi) {
-        if (mSysuiProxy != null) {
-            mSysuiProxy.requestTopUi(requestTopUi, TAG);
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java
deleted file mode 100644
index 20c4d5a..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SnapshotWindowCreator.java
+++ /dev/null
@@ -1,70 +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.startingsurface;
-
-import android.window.StartingWindowInfo;
-import android.window.TaskSnapshot;
-
-import com.android.wm.shell.common.ShellExecutor;
-
-class SnapshotWindowCreator {
-    private final ShellExecutor mMainExecutor;
-    private final StartingSurfaceDrawer.StartingWindowRecordManager
-            mStartingWindowRecordManager;
-
-    SnapshotWindowCreator(ShellExecutor mainExecutor,
-            StartingSurfaceDrawer.StartingWindowRecordManager startingWindowRecordManager) {
-        mMainExecutor = mainExecutor;
-        mStartingWindowRecordManager = startingWindowRecordManager;
-    }
-
-    void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, TaskSnapshot snapshot) {
-        final int taskId = startingWindowInfo.taskInfo.taskId;
-        // Remove any existing starting window for this task before adding.
-        mStartingWindowRecordManager.removeWindow(taskId, true);
-        final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo,
-                startingWindowInfo.appToken, snapshot, mMainExecutor,
-                () -> mStartingWindowRecordManager.removeWindow(taskId, true));
-        if (surface != null) {
-            final SnapshotWindowRecord tView = new SnapshotWindowRecord(surface,
-                    startingWindowInfo.taskInfo.topActivityType, mMainExecutor);
-            mStartingWindowRecordManager.addRecord(taskId, tView);
-        }
-    }
-
-    private static class SnapshotWindowRecord extends StartingSurfaceDrawer.SnapshotRecord {
-        private final TaskSnapshotWindow mTaskSnapshotWindow;
-
-        SnapshotWindowRecord(TaskSnapshotWindow taskSnapshotWindow,
-                int activityType, ShellExecutor removeExecutor) {
-            super(activityType, removeExecutor);
-            mTaskSnapshotWindow = taskSnapshotWindow;
-            mBGColor = mTaskSnapshotWindow.getBackgroundColor();
-        }
-
-        @Override
-        protected void removeImmediately() {
-            super.removeImmediately();
-            mTaskSnapshotWindow.removeImmediately();
-        }
-
-        @Override
-        protected boolean hasImeSurface() {
-            return mTaskSnapshotWindow.hasImeSurface();
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 79cd891..ebb957b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -24,6 +24,9 @@
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN;
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
 
+import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MAX_ANIMATION_DURATION;
+import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MINIMAL_ANIMATION_DURATION;
+
 import android.annotation.ColorInt;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -93,25 +96,6 @@
 public class SplashscreenContentDrawer {
     private static final String TAG = StartingWindowController.TAG;
 
-    /**
-     * The minimum duration during which the splash screen is shown when the splash screen icon is
-     * animated.
-     */
-    static final long MINIMAL_ANIMATION_DURATION = 400L;
-
-    /**
-     * Allow the icon style splash screen to be displayed for longer to give time for the animation
-     * to finish, i.e. the extra buffer time to keep the splash screen if the animation is slightly
-     * longer than the {@link #MINIMAL_ANIMATION_DURATION} duration.
-     */
-    static final long TIME_WINDOW_DURATION = 100L;
-
-    /**
-     * The maximum duration during which the splash screen will be shown if the application is ready
-     * to show before the icon animation finishes.
-     */
-    static final long MAX_ANIMATION_DURATION = MINIMAL_ANIMATION_DURATION + TIME_WINDOW_DURATION;
-
     // The acceptable area ratio of foreground_icon_area/background_icon_area, if there is an
     // icon which it's non-transparent foreground area is similar to it's background area, then
     // do not enlarge the foreground drawable.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
deleted file mode 100644
index 4db81e2..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
+++ /dev/null
@@ -1,506 +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.startingsurface;
-
-import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.view.Choreographer.CALLBACK_INSETS_ANIMATION;
-import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
-
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
-import android.app.ActivityThread;
-import android.app.TaskInfo;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.res.TypedArray;
-import android.graphics.Color;
-import android.graphics.PixelFormat;
-import android.hardware.display.DisplayManager;
-import android.os.IBinder;
-import android.os.RemoteCallback;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.Trace;
-import android.os.UserHandle;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.view.Choreographer;
-import android.view.Display;
-import android.view.SurfaceControlViewHost;
-import android.view.View;
-import android.view.WindowInsetsController;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-import android.widget.FrameLayout;
-import android.window.SplashScreenView;
-import android.window.StartingWindowInfo;
-import android.window.StartingWindowRemovalInfo;
-
-import com.android.internal.R;
-import com.android.internal.protolog.common.ProtoLog;
-import com.android.internal.util.ContrastColorUtil;
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.protolog.ShellProtoLogGroup;
-
-import java.util.function.Supplier;
-
-/**
- * A class which able to draw splash screen as the starting window for a task.
- *
- * In order to speed up, there will use two threads to creating a splash screen in parallel.
- * Right now we are still using PhoneWindow to create splash screen window, so the view is added to
- * the ViewRootImpl, and those view won't be draw immediately because the ViewRootImpl will call
- * scheduleTraversal to register a callback from Choreographer, so the drawing result of the view
- * can synchronize on each frame.
- *
- * The bad thing is that we cannot decide when would Choreographer#doFrame happen, and drawing
- * the AdaptiveIconDrawable object can be time consuming, so we use the splash-screen background
- * thread to draw the AdaptiveIconDrawable object to a Bitmap and cache it to a BitmapShader after
- * the SplashScreenView just created, once we get the BitmapShader then the #draw call can be very
- * quickly.
- *
- * So basically we are using the spare time to prepare the SplashScreenView while splash screen
- * thread is waiting for
- * 1. WindowManager#addView(binder call to WM),
- * 2. Choreographer#doFrame happen(uncertain time for next frame, depends on device),
- * 3. Session#relayout(another binder call to WM which under Choreographer#doFrame, but will
- * always happen before #draw).
- * Because above steps are running on splash-screen thread, so pre-draw the BitmapShader on
- * splash-screen background tread can make they execute in parallel, which ensure it is faster then
- * to draw the AdaptiveIconDrawable when receive callback from Choreographer#doFrame.
- *
- * Here is the sequence to compare the difference between using single and two thread.
- *
- * Single thread:
- * => makeSplashScreenContentView -> WM#addView .. waiting for Choreographer#doFrame -> relayout
- * -> draw -> AdaptiveIconDrawable#draw
- *
- * Two threads:
- * => makeSplashScreenContentView -> cachePaint(=AdaptiveIconDrawable#draw)
- * => WM#addView -> .. waiting for Choreographer#doFrame -> relayout -> draw -> (draw the Paint
- * directly).
- */
-class SplashscreenWindowCreator extends AbsSplashWindowCreator {
-    private static final int LIGHT_BARS_MASK =
-            WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
-                    | WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
-
-    private final WindowManagerGlobal mWindowManagerGlobal;
-    private Choreographer mChoreographer;
-
-    /**
-     * Records of {@link SurfaceControlViewHost} where the splash screen icon animation is
-     * rendered and that have not yet been removed by their client.
-     */
-    private final SparseArray<SurfaceControlViewHost> mAnimatedSplashScreenSurfaceHosts =
-            new SparseArray<>(1);
-
-    SplashscreenWindowCreator(SplashscreenContentDrawer contentDrawer, Context context,
-            ShellExecutor splashScreenExecutor, DisplayManager displayManager,
-            StartingSurfaceDrawer.StartingWindowRecordManager startingWindowRecordManager) {
-        super(contentDrawer, context, splashScreenExecutor, displayManager,
-                startingWindowRecordManager);
-        mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance());
-        mWindowManagerGlobal = WindowManagerGlobal.getInstance();
-    }
-
-    void addSplashScreenStartingWindow(StartingWindowInfo windowInfo,
-            @StartingWindowInfo.StartingWindowType int suggestType) {
-        final ActivityManager.RunningTaskInfo taskInfo = windowInfo.taskInfo;
-        final ActivityInfo activityInfo = windowInfo.targetActivityInfo != null
-                ? windowInfo.targetActivityInfo
-                : taskInfo.topActivityInfo;
-        if (activityInfo == null || activityInfo.packageName == null) {
-            return;
-        }
-        // replace with the default theme if the application didn't set
-        final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo);
-        final Context context = SplashscreenContentDrawer.createContext(mContext, windowInfo, theme,
-                suggestType, mDisplayManager);
-        if (context == null) {
-            return;
-        }
-        final WindowManager.LayoutParams params = SplashscreenContentDrawer.createLayoutParameters(
-                context, windowInfo, suggestType, activityInfo.packageName,
-                suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
-                        ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT, windowInfo.appToken);
-
-        final int displayId = taskInfo.displayId;
-        final int taskId = taskInfo.taskId;
-        final Display display = getDisplay(displayId);
-
-        // TODO(b/173975965) tracking performance
-        // Prepare the splash screen content view on splash screen worker thread in parallel, so the
-        // content view won't be blocked by binder call like addWindow and relayout.
-        // 1. Trigger splash screen worker thread to create SplashScreenView before/while
-        // Session#addWindow.
-        // 2. Synchronize the SplashscreenView to splash screen thread before Choreographer start
-        // traversal, which will call Session#relayout on splash screen thread.
-        // 3. Pre-draw the BitmapShader if the icon is immobile on splash screen worker thread, at
-        // the same time the splash screen thread should be executing Session#relayout. Blocking the
-        // traversal -> draw on splash screen thread until the BitmapShader of the icon is ready.
-
-        // Record whether create splash screen view success, notify to current thread after
-        // create splash screen view finished.
-        final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
-        final FrameLayout rootLayout = new FrameLayout(
-                mSplashscreenContentDrawer.createViewContextWrapper(context));
-        rootLayout.setPadding(0, 0, 0, 0);
-        rootLayout.setFitsSystemWindows(false);
-        final Runnable setViewSynchronized = () -> {
-            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addSplashScreenView");
-            // waiting for setContentView before relayoutWindow
-            SplashScreenView contentView = viewSupplier.get();
-            final StartingSurfaceDrawer.StartingWindowRecord sRecord =
-                    mStartingWindowRecordManager.getRecord(taskId);
-            final SplashWindowRecord record = sRecord instanceof SplashWindowRecord
-                    ? (SplashWindowRecord) sRecord : null;
-            // If record == null, either the starting window added fail or removed already.
-            // Do not add this view if the token is mismatch.
-            if (record != null && windowInfo.appToken == record.mAppToken) {
-                // if view == null then creation of content view was failed.
-                if (contentView != null) {
-                    try {
-                        rootLayout.addView(contentView);
-                    } catch (RuntimeException e) {
-                        Slog.w(TAG, "failed set content view to starting window "
-                                + "at taskId: " + taskId, e);
-                        contentView = null;
-                    }
-                }
-                record.setSplashScreenView(contentView);
-            }
-            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-        };
-        requestTopUi(true);
-        mSplashscreenContentDrawer.createContentView(context, suggestType, windowInfo,
-                viewSupplier::setView, viewSupplier::setUiThreadInitTask);
-        try {
-            if (addWindow(taskId, windowInfo.appToken, rootLayout, display, params, suggestType)) {
-                // We use the splash screen worker thread to create SplashScreenView while adding
-                // the window, as otherwise Choreographer#doFrame might be delayed on this thread.
-                // And since Choreographer#doFrame won't happen immediately after adding the window,
-                // if the view is not added to the PhoneWindow on the first #doFrame, the view will
-                // not be rendered on the first frame. So here we need to synchronize the view on
-                // the window before first round relayoutWindow, which will happen after insets
-                // animation.
-                mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null);
-                final SplashWindowRecord record =
-                        (SplashWindowRecord) mStartingWindowRecordManager.getRecord(taskId);
-                if (record != null) {
-                    record.parseAppSystemBarColor(context);
-                    // Block until we get the background color.
-                    final SplashScreenView contentView = viewSupplier.get();
-                    if (suggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
-                        contentView.addOnAttachStateChangeListener(
-                                new View.OnAttachStateChangeListener() {
-                                    @Override
-                                    public void onViewAttachedToWindow(View v) {
-                                        final int lightBarAppearance =
-                                                ContrastColorUtil.isColorLight(
-                                                        contentView.getInitBackgroundColor())
-                                                        ? LIGHT_BARS_MASK : 0;
-                                        contentView.getWindowInsetsController()
-                                                .setSystemBarsAppearance(
-                                                lightBarAppearance, LIGHT_BARS_MASK);
-                                    }
-
-                                    @Override
-                                    public void onViewDetachedFromWindow(View v) {
-                                    }
-                                });
-                    }
-                }
-            } else {
-                // release the icon view host
-                final SplashScreenView contentView = viewSupplier.get();
-                if (contentView.getSurfaceHost() != null) {
-                    SplashScreenView.releaseIconHost(contentView.getSurfaceHost());
-                }
-            }
-        } catch (RuntimeException e) {
-            // don't crash if something else bad happens, for example a
-            // failure loading resources because we are loading from an app
-            // on external storage that has been unmounted.
-            Slog.w(TAG, "failed creating starting window at taskId: " + taskId, e);
-        }
-    }
-
-    int estimateTaskBackgroundColor(TaskInfo taskInfo) {
-        if (taskInfo.topActivityInfo == null) {
-            return Color.TRANSPARENT;
-        }
-        final ActivityInfo activityInfo = taskInfo.topActivityInfo;
-        final String packageName = activityInfo.packageName;
-        final int userId = taskInfo.userId;
-        final Context windowContext;
-        try {
-            windowContext = mContext.createPackageContextAsUser(
-                    packageName, Context.CONTEXT_RESTRICTED, UserHandle.of(userId));
-        } catch (PackageManager.NameNotFoundException e) {
-            Slog.w(TAG, "Failed creating package context with package name "
-                    + packageName + " for user " + taskInfo.userId, e);
-            return Color.TRANSPARENT;
-        }
-        try {
-            final IPackageManager packageManager = ActivityThread.getPackageManager();
-            final String splashScreenThemeName = packageManager.getSplashScreenTheme(packageName,
-                    userId);
-            final int splashScreenThemeId = splashScreenThemeName != null
-                    ? windowContext.getResources().getIdentifier(splashScreenThemeName, null, null)
-                    : 0;
-
-            final int theme = getSplashScreenTheme(splashScreenThemeId, activityInfo);
-
-            if (theme != windowContext.getThemeResId()) {
-                windowContext.setTheme(theme);
-            }
-            return mSplashscreenContentDrawer.estimateTaskBackgroundColor(windowContext);
-        } catch (RuntimeException | RemoteException e) {
-            Slog.w(TAG, "failed get starting window background color at taskId: "
-                    + taskInfo.taskId, e);
-        }
-        return Color.TRANSPARENT;
-    }
-
-    /**
-     * Called when the Task wants to copy the splash screen.
-     */
-    public void copySplashScreenView(int taskId) {
-        final StartingSurfaceDrawer.StartingWindowRecord record =
-                mStartingWindowRecordManager.getRecord(taskId);
-        final SplashWindowRecord preView = record instanceof SplashWindowRecord
-                ? (SplashWindowRecord) record : null;
-        SplashScreenView.SplashScreenViewParcelable parcelable;
-        SplashScreenView splashScreenView = preView != null ? preView.mSplashView : null;
-        if (splashScreenView != null && splashScreenView.isCopyable()) {
-            parcelable = new SplashScreenView.SplashScreenViewParcelable(splashScreenView);
-            parcelable.setClientCallback(
-                    new RemoteCallback((bundle) -> mSplashScreenExecutor.execute(
-                            () -> onAppSplashScreenViewRemoved(taskId, false))));
-            splashScreenView.onCopied();
-            mAnimatedSplashScreenSurfaceHosts.append(taskId, splashScreenView.getSurfaceHost());
-        } else {
-            parcelable = null;
-        }
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
-                "Copying splash screen window view for task: %d with parcelable %b",
-                taskId, parcelable != null);
-        ActivityTaskManager.getInstance().onSplashScreenViewCopyFinished(taskId, parcelable);
-    }
-
-    /**
-     * Called when the {@link SplashScreenView} is removed from the client Activity view's hierarchy
-     * or when the Activity is clean up.
-     *
-     * @param taskId The Task id on which the splash screen was attached
-     */
-    public void onAppSplashScreenViewRemoved(int taskId) {
-        onAppSplashScreenViewRemoved(taskId, true /* fromServer */);
-    }
-
-    /**
-     * @param fromServer If true, this means the removal was notified by the server. This is only
-     *                   used for debugging purposes.
-     * @see #onAppSplashScreenViewRemoved(int)
-     */
-    private void onAppSplashScreenViewRemoved(int taskId, boolean fromServer) {
-        SurfaceControlViewHost viewHost =
-                mAnimatedSplashScreenSurfaceHosts.get(taskId);
-        if (viewHost == null) {
-            return;
-        }
-        mAnimatedSplashScreenSurfaceHosts.remove(taskId);
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
-                "%s the splash screen. Releasing SurfaceControlViewHost for task: %d",
-                fromServer ? "Server cleaned up" : "App removed", taskId);
-        SplashScreenView.releaseIconHost(viewHost);
-    }
-
-    protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,
-            WindowManager.LayoutParams params,
-            @StartingWindowInfo.StartingWindowType int suggestType) {
-        boolean shouldSaveView = true;
-        final Context context = view.getContext();
-        try {
-            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
-            mWindowManagerGlobal.addView(view, params, display,
-                    null /* parentWindow */, context.getUserId());
-        } catch (WindowManager.BadTokenException e) {
-            // ignore
-            Slog.w(TAG, appToken + " already running, starting window not displayed. "
-                    + e.getMessage());
-            shouldSaveView = false;
-        } finally {
-            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-            if (view.getParent() == null) {
-                Slog.w(TAG, "view not successfully added to wm, removing view");
-                mWindowManagerGlobal.removeView(view, true /* immediate */);
-                shouldSaveView = false;
-            }
-        }
-        if (shouldSaveView) {
-            mStartingWindowRecordManager.removeWindow(taskId, true);
-            saveSplashScreenRecord(appToken, taskId, view, suggestType);
-        }
-        return shouldSaveView;
-    }
-
-    private void saveSplashScreenRecord(IBinder appToken, int taskId, View view,
-            @StartingWindowInfo.StartingWindowType int suggestType) {
-        final SplashWindowRecord tView =
-                new SplashWindowRecord(appToken, view, suggestType);
-        mStartingWindowRecordManager.addRecord(taskId, tView);
-    }
-
-    private void removeWindowInner(View decorView, boolean hideView) {
-        requestTopUi(false);
-        if (hideView) {
-            decorView.setVisibility(View.GONE);
-        }
-        mWindowManagerGlobal.removeView(decorView, false /* immediate */);
-    }
-
-    private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
-        private SplashScreenView mView;
-        private boolean mIsViewSet;
-        private Runnable mUiThreadInitTask;
-        void setView(SplashScreenView view) {
-            synchronized (this) {
-                mView = view;
-                mIsViewSet = true;
-                notify();
-            }
-        }
-
-        void setUiThreadInitTask(Runnable initTask) {
-            synchronized (this) {
-                mUiThreadInitTask = initTask;
-            }
-        }
-
-        @Override
-        @Nullable
-        public SplashScreenView get() {
-            synchronized (this) {
-                while (!mIsViewSet) {
-                    try {
-                        wait();
-                    } catch (InterruptedException ignored) {
-                    }
-                }
-                if (mUiThreadInitTask != null) {
-                    mUiThreadInitTask.run();
-                    mUiThreadInitTask = null;
-                }
-                return mView;
-            }
-        }
-    }
-
-    private class SplashWindowRecord extends StartingSurfaceDrawer.StartingWindowRecord {
-        private final IBinder mAppToken;
-        private final View mRootView;
-        @StartingWindowInfo.StartingWindowType private final int mSuggestType;
-        private final long mCreateTime;
-
-        private boolean mSetSplashScreen;
-        private SplashScreenView mSplashView;
-        private int mSystemBarAppearance;
-        private boolean mDrawsSystemBarBackgrounds;
-
-        SplashWindowRecord(IBinder appToken, View decorView,
-                @StartingWindowInfo.StartingWindowType int suggestType) {
-            mAppToken = appToken;
-            mRootView = decorView;
-            mSuggestType = suggestType;
-            mCreateTime = SystemClock.uptimeMillis();
-        }
-
-        void setSplashScreenView(SplashScreenView splashScreenView) {
-            if (mSetSplashScreen) {
-                return;
-            }
-            mSplashView = splashScreenView;
-            mBGColor = mSplashView.getInitBackgroundColor();
-            mSetSplashScreen = true;
-        }
-
-        void parseAppSystemBarColor(Context context) {
-            final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
-            mDrawsSystemBarBackgrounds = a.getBoolean(
-                    R.styleable.Window_windowDrawsSystemBarBackgrounds, false);
-            if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
-                mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
-            }
-            if (a.getBoolean(R.styleable.Window_windowLightNavigationBar, false)) {
-                mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
-            }
-            a.recycle();
-        }
-
-        // Reset the system bar color which set by splash screen, make it align to the app.
-        void clearSystemBarColor() {
-            if (mRootView == null || !mRootView.isAttachedToWindow()) {
-                return;
-            }
-            if (mRootView.getLayoutParams() instanceof WindowManager.LayoutParams) {
-                final WindowManager.LayoutParams lp =
-                        (WindowManager.LayoutParams) mRootView.getLayoutParams();
-                if (mDrawsSystemBarBackgrounds) {
-                    lp.flags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-                } else {
-                    lp.flags &= ~WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-                }
-                mRootView.setLayoutParams(lp);
-            }
-            mRootView.getWindowInsetsController().setSystemBarsAppearance(
-                    mSystemBarAppearance, LIGHT_BARS_MASK);
-        }
-
-        @Override
-        public void removeIfPossible(StartingWindowRemovalInfo info, boolean immediately) {
-            if (mRootView != null) {
-                if (mSplashView != null) {
-                    clearSystemBarColor();
-                    if (immediately
-                            || mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
-                        removeWindowInner(mRootView, false);
-                    } else {
-                        if (info.playRevealAnimation) {
-                            mSplashscreenContentDrawer.applyExitAnimation(mSplashView,
-                                    info.windowAnimationLeash, info.mainFrame,
-                                    () -> removeWindowInner(mRootView, true),
-                                    mCreateTime, info.roundedCornerRadius);
-                        } else {
-                            // the SplashScreenView has been copied to client, hide the view to skip
-                            // default exit animation
-                            removeWindowInner(mRootView, true);
-                        }
-                    }
-                } else {
-                    // shouldn't happen
-                    Slog.e(TAG, "Found empty splash screen, remove!");
-                    removeWindowInner(mRootView, false);
-                }
-            }
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index ff06db3..4f07bfe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -16,80 +16,169 @@
 
 package com.android.wm.shell.startingsurface;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.view.Choreographer.CALLBACK_INSETS_ANIMATION;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
 
-import android.annotation.CallSuper;
+import android.annotation.Nullable;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityTaskManager;
+import android.app.ActivityThread;
 import android.app.TaskInfo;
-import android.app.WindowConfiguration;
 import android.content.Context;
-import android.content.res.Configuration;
+import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.res.TypedArray;
 import android.graphics.Color;
+import android.graphics.PixelFormat;
 import android.hardware.display.DisplayManager;
+import android.os.IBinder;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.Trace;
+import android.os.UserHandle;
+import android.util.Slog;
 import android.util.SparseArray;
-import android.view.IWindow;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
+import android.view.Choreographer;
+import android.view.Display;
+import android.view.SurfaceControlViewHost;
+import android.view.View;
+import android.view.WindowInsetsController;
 import android.view.WindowManager;
-import android.view.WindowlessWindowManager;
+import android.view.WindowManagerGlobal;
+import android.widget.FrameLayout;
 import android.window.SplashScreenView;
+import android.window.SplashScreenView.SplashScreenViewParcelable;
 import android.window.StartingWindowInfo;
 import android.window.StartingWindowInfo.StartingWindowType;
 import android.window.StartingWindowRemovalInfo;
 import android.window.TaskSnapshot;
 
+import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.internal.util.ContrastColorUtil;
 import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
+import java.util.function.Supplier;
+
 /**
  * A class which able to draw splash screen or snapshot as the starting window for a task.
+ *
+ * In order to speed up, there will use two threads to creating a splash screen in parallel.
+ * Right now we are still using PhoneWindow to create splash screen window, so the view is added to
+ * the ViewRootImpl, and those view won't be draw immediately because the ViewRootImpl will call
+ * scheduleTraversal to register a callback from Choreographer, so the drawing result of the view
+ * can synchronize on each frame.
+ *
+ * The bad thing is that we cannot decide when would Choreographer#doFrame happen, and drawing
+ * the AdaptiveIconDrawable object can be time consuming, so we use the splash-screen background
+ * thread to draw the AdaptiveIconDrawable object to a Bitmap and cache it to a BitmapShader after
+ * the SplashScreenView just created, once we get the BitmapShader then the #draw call can be very
+ * quickly.
+ *
+ * So basically we are using the spare time to prepare the SplashScreenView while splash screen
+ * thread is waiting for
+ * 1. WindowManager#addView(binder call to WM),
+ * 2. Choreographer#doFrame happen(uncertain time for next frame, depends on device),
+ * 3. Session#relayout(another binder call to WM which under Choreographer#doFrame, but will
+ * always happen before #draw).
+ * Because above steps are running on splash-screen thread, so pre-draw the BitmapShader on
+ * splash-screen background tread can make they execute in parallel, which ensure it is faster then
+ * to draw the AdaptiveIconDrawable when receive callback from Choreographer#doFrame.
+ *
+ * Here is the sequence to compare the difference between using single and two thread.
+ *
+ * Single thread:
+ * => makeSplashScreenContentView -> WM#addView .. waiting for Choreographer#doFrame -> relayout
+ * -> draw -> AdaptiveIconDrawable#draw
+ *
+ * Two threads:
+ * => makeSplashScreenContentView -> cachePaint(=AdaptiveIconDrawable#draw)
+ * => WM#addView -> .. waiting for Choreographer#doFrame -> relayout -> draw -> (draw the Paint
+ * directly).
  */
 @ShellSplashscreenThread
 public class StartingSurfaceDrawer {
+    private static final String TAG = StartingWindowController.TAG;
 
+    private final Context mContext;
+    private final DisplayManager mDisplayManager;
     private final ShellExecutor mSplashScreenExecutor;
     @VisibleForTesting
     final SplashscreenContentDrawer mSplashscreenContentDrawer;
-    @VisibleForTesting
-    final SplashscreenWindowCreator mSplashscreenWindowCreator;
-    private final SnapshotWindowCreator mSnapshotWindowCreator;
-    private final WindowlessSplashWindowCreator mWindowlessSplashWindowCreator;
-    private final WindowlessSnapshotWindowCreator mWindowlessSnapshotWindowCreator;
+    private Choreographer mChoreographer;
+    private final WindowManagerGlobal mWindowManagerGlobal;
+    private StartingSurface.SysuiProxy mSysuiProxy;
+    private final StartingWindowRemovalInfo mTmpRemovalInfo = new StartingWindowRemovalInfo();
 
-    @VisibleForTesting
-    final StartingWindowRecordManager mWindowRecords = new StartingWindowRecordManager();
-    // Windowless surface could co-exist with starting window in a task.
-    @VisibleForTesting
-    final StartingWindowRecordManager mWindowlessRecords = new StartingWindowRecordManager();
+    private static final int LIGHT_BARS_MASK =
+            WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
+                    | WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
+    /**
+     * The minimum duration during which the splash screen is shown when the splash screen icon is
+     * animated.
+     */
+    static final long MINIMAL_ANIMATION_DURATION = 400L;
+
+    /**
+     * Allow the icon style splash screen to be displayed for longer to give time for the animation
+     * to finish, i.e. the extra buffer time to keep the splash screen if the animation is slightly
+     * longer than the {@link #MINIMAL_ANIMATION_DURATION} duration.
+     */
+    static final long TIME_WINDOW_DURATION = 100L;
+
+    /**
+     * The maximum duration during which the splash screen will be shown if the application is ready
+     * to show before the icon animation finishes.
+     */
+    static final long MAX_ANIMATION_DURATION = MINIMAL_ANIMATION_DURATION + TIME_WINDOW_DURATION;
+
     /**
      * @param splashScreenExecutor The thread used to control add and remove starting window.
      */
     public StartingSurfaceDrawer(Context context, ShellExecutor splashScreenExecutor,
             IconProvider iconProvider, TransactionPool pool) {
+        mContext = context;
+        mDisplayManager = mContext.getSystemService(DisplayManager.class);
         mSplashScreenExecutor = splashScreenExecutor;
-        final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
-        mSplashscreenContentDrawer = new SplashscreenContentDrawer(context, iconProvider, pool);
-        displayManager.getDisplay(DEFAULT_DISPLAY);
+        mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, iconProvider, pool);
+        mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance());
+        mWindowManagerGlobal = WindowManagerGlobal.getInstance();
+        mDisplayManager.getDisplay(DEFAULT_DISPLAY);
+    }
 
-        mSplashscreenWindowCreator = new SplashscreenWindowCreator(mSplashscreenContentDrawer,
-                context, splashScreenExecutor, displayManager, mWindowRecords);
-        mSnapshotWindowCreator = new SnapshotWindowCreator(splashScreenExecutor,
-                mWindowRecords);
-        mWindowlessSplashWindowCreator = new WindowlessSplashWindowCreator(
-                mSplashscreenContentDrawer, context, splashScreenExecutor, displayManager,
-                mWindowlessRecords, pool);
-        mWindowlessSnapshotWindowCreator = new WindowlessSnapshotWindowCreator(
-                mWindowlessRecords, context, displayManager, mSplashscreenContentDrawer, pool);
+    @VisibleForTesting
+    final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>();
+
+    /**
+     * Records of {@link SurfaceControlViewHost} where the splash screen icon animation is
+     * rendered and that have not yet been removed by their client.
+     */
+    private final SparseArray<SurfaceControlViewHost> mAnimatedSplashScreenSurfaceHosts =
+            new SparseArray<>(1);
+
+    private Display getDisplay(int displayId) {
+        return mDisplayManager.getDisplay(displayId);
+    }
+
+    int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) {
+        return splashScreenThemeResId != 0
+                ? splashScreenThemeResId
+                : activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource()
+                        : com.android.internal.R.style.Theme_DeviceDefault_DayNight;
     }
 
     void setSysuiProxy(StartingSurface.SysuiProxy sysuiProxy) {
-        mSplashscreenWindowCreator.setSysuiProxy(sysuiProxy);
-        mWindowlessSplashWindowCreator.setSysuiProxy(sysuiProxy);
+        mSysuiProxy = sysuiProxy;
     }
 
     /**
@@ -97,55 +186,231 @@
      *
      * @param suggestType The suggestion type to draw the splash screen.
      */
-    void addSplashScreenStartingWindow(StartingWindowInfo windowInfo,
+    void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken,
             @StartingWindowType int suggestType) {
-        mSplashscreenWindowCreator.addSplashScreenStartingWindow(windowInfo, suggestType);
+        final RunningTaskInfo taskInfo = windowInfo.taskInfo;
+        final ActivityInfo activityInfo = windowInfo.targetActivityInfo != null
+                ? windowInfo.targetActivityInfo
+                : taskInfo.topActivityInfo;
+        if (activityInfo == null || activityInfo.packageName == null) {
+            return;
+        }
+        // replace with the default theme if the application didn't set
+        final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo);
+        final Context context = SplashscreenContentDrawer.createContext(mContext, windowInfo, theme,
+                suggestType, mDisplayManager);
+        if (context == null) {
+            return;
+        }
+        final WindowManager.LayoutParams params = SplashscreenContentDrawer.createLayoutParameters(
+                context, windowInfo, suggestType, activityInfo.packageName,
+                suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
+                        ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT, appToken);
+
+        final int displayId = taskInfo.displayId;
+        final int taskId = taskInfo.taskId;
+        final Display display = getDisplay(displayId);
+
+        // TODO(b/173975965) tracking performance
+        // Prepare the splash screen content view on splash screen worker thread in parallel, so the
+        // content view won't be blocked by binder call like addWindow and relayout.
+        // 1. Trigger splash screen worker thread to create SplashScreenView before/while
+        // Session#addWindow.
+        // 2. Synchronize the SplashscreenView to splash screen thread before Choreographer start
+        // traversal, which will call Session#relayout on splash screen thread.
+        // 3. Pre-draw the BitmapShader if the icon is immobile on splash screen worker thread, at
+        // the same time the splash screen thread should be executing Session#relayout. Blocking the
+        // traversal -> draw on splash screen thread until the BitmapShader of the icon is ready.
+
+        // Record whether create splash screen view success, notify to current thread after
+        // create splash screen view finished.
+        final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
+        final FrameLayout rootLayout = new FrameLayout(
+                mSplashscreenContentDrawer.createViewContextWrapper(context));
+        rootLayout.setPadding(0, 0, 0, 0);
+        rootLayout.setFitsSystemWindows(false);
+        final Runnable setViewSynchronized = () -> {
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addSplashScreenView");
+            // waiting for setContentView before relayoutWindow
+            SplashScreenView contentView = viewSupplier.get();
+            final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
+            // If record == null, either the starting window added fail or removed already.
+            // Do not add this view if the token is mismatch.
+            if (record != null && appToken == record.mAppToken) {
+                // if view == null then creation of content view was failed.
+                if (contentView != null) {
+                    try {
+                        rootLayout.addView(contentView);
+                    } catch (RuntimeException e) {
+                        Slog.w(TAG, "failed set content view to starting window "
+                                + "at taskId: " + taskId, e);
+                        contentView = null;
+                    }
+                }
+                record.setSplashScreenView(contentView);
+            }
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+        };
+        if (mSysuiProxy != null) {
+            mSysuiProxy.requestTopUi(true, TAG);
+        }
+        mSplashscreenContentDrawer.createContentView(context, suggestType, windowInfo,
+                viewSupplier::setView, viewSupplier::setUiThreadInitTask);
+        try {
+            if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) {
+                // We use the splash screen worker thread to create SplashScreenView while adding
+                // the window, as otherwise Choreographer#doFrame might be delayed on this thread.
+                // And since Choreographer#doFrame won't happen immediately after adding the window,
+                // if the view is not added to the PhoneWindow on the first #doFrame, the view will
+                // not be rendered on the first frame. So here we need to synchronize the view on
+                // the window before first round relayoutWindow, which will happen after insets
+                // animation.
+                mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null);
+                final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
+                record.parseAppSystemBarColor(context);
+                // Block until we get the background color.
+                final SplashScreenView contentView = viewSupplier.get();
+                if (suggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+                    contentView.addOnAttachStateChangeListener(
+                            new View.OnAttachStateChangeListener() {
+                                @Override
+                                public void onViewAttachedToWindow(View v) {
+                                    final int lightBarAppearance = ContrastColorUtil.isColorLight(
+                                            contentView.getInitBackgroundColor())
+                                            ? LIGHT_BARS_MASK : 0;
+                                    contentView.getWindowInsetsController().setSystemBarsAppearance(
+                                            lightBarAppearance, LIGHT_BARS_MASK);
+                                }
+
+                                @Override
+                                public void onViewDetachedFromWindow(View v) {
+                                }
+                            });
+                }
+                record.mBGColor = contentView.getInitBackgroundColor();
+            } else {
+                // release the icon view host
+                final SplashScreenView contentView = viewSupplier.get();
+                if (contentView.getSurfaceHost() != null) {
+                    SplashScreenView.releaseIconHost(contentView.getSurfaceHost());
+                }
+            }
+        } catch (RuntimeException e) {
+            // don't crash if something else bad happens, for example a
+            // failure loading resources because we are loading from an app
+            // on external storage that has been unmounted.
+            Slog.w(TAG, "failed creating starting window at taskId: " + taskId, e);
+        }
     }
 
     int getStartingWindowBackgroundColorForTask(int taskId) {
-        final StartingWindowRecord startingWindowRecord = mWindowRecords.getRecord(taskId);
+        final StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
         if (startingWindowRecord == null) {
             return Color.TRANSPARENT;
         }
-        return startingWindowRecord.getBGColor();
+        return startingWindowRecord.mBGColor;
+    }
+
+    private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
+        private SplashScreenView mView;
+        private boolean mIsViewSet;
+        private Runnable mUiThreadInitTask;
+        void setView(SplashScreenView view) {
+            synchronized (this) {
+                mView = view;
+                mIsViewSet = true;
+                notify();
+            }
+        }
+
+        void setUiThreadInitTask(Runnable initTask) {
+            synchronized (this) {
+                mUiThreadInitTask = initTask;
+            }
+        }
+
+        @Override
+        @Nullable
+        public SplashScreenView get() {
+            synchronized (this) {
+                while (!mIsViewSet) {
+                    try {
+                        wait();
+                    } catch (InterruptedException ignored) {
+                    }
+                }
+                if (mUiThreadInitTask != null) {
+                    mUiThreadInitTask.run();
+                    mUiThreadInitTask = null;
+                }
+                return mView;
+            }
+        }
     }
 
     int estimateTaskBackgroundColor(TaskInfo taskInfo) {
-        return mSplashscreenWindowCreator.estimateTaskBackgroundColor(taskInfo);
+        if (taskInfo.topActivityInfo == null) {
+            return Color.TRANSPARENT;
+        }
+        final ActivityInfo activityInfo = taskInfo.topActivityInfo;
+        final String packageName = activityInfo.packageName;
+        final int userId = taskInfo.userId;
+        final Context windowContext;
+        try {
+            windowContext = mContext.createPackageContextAsUser(
+                    packageName, Context.CONTEXT_RESTRICTED, UserHandle.of(userId));
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.w(TAG, "Failed creating package context with package name "
+                    + packageName + " for user " + taskInfo.userId, e);
+            return Color.TRANSPARENT;
+        }
+        try {
+            final IPackageManager packageManager = ActivityThread.getPackageManager();
+            final String splashScreenThemeName = packageManager.getSplashScreenTheme(packageName,
+                    userId);
+            final int splashScreenThemeId = splashScreenThemeName != null
+                    ? windowContext.getResources().getIdentifier(splashScreenThemeName, null, null)
+                    : 0;
+
+            final int theme = getSplashScreenTheme(splashScreenThemeId, activityInfo);
+
+            if (theme != windowContext.getThemeResId()) {
+                windowContext.setTheme(theme);
+            }
+            return mSplashscreenContentDrawer.estimateTaskBackgroundColor(windowContext);
+        } catch (RuntimeException | RemoteException e) {
+            Slog.w(TAG, "failed get starting window background color at taskId: "
+                    + taskInfo.taskId, e);
+        }
+        return Color.TRANSPARENT;
     }
 
     /**
      * Called when a task need a snapshot starting window.
      */
-    void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, TaskSnapshot snapshot) {
-        mSnapshotWindowCreator.makeTaskSnapshotWindow(startingWindowInfo, snapshot);
+    void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, IBinder appToken,
+            TaskSnapshot snapshot) {
+        final int taskId = startingWindowInfo.taskInfo.taskId;
+        // Remove any existing starting window for this task before adding.
+        removeWindowNoAnimate(taskId);
+        final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken,
+                snapshot, mSplashScreenExecutor, () -> removeWindowNoAnimate(taskId));
+        if (surface == null) {
+            return;
+        }
+        final StartingWindowRecord tView = new StartingWindowRecord(appToken,
+                null/* decorView */, surface, STARTING_WINDOW_TYPE_SNAPSHOT);
+        mStartingWindowRecords.put(taskId, tView);
     }
 
     /**
      * Called when the content of a task is ready to show, starting window can be removed.
      */
     public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) {
-        if (removalInfo.windowlessSurface) {
-            mWindowlessRecords.removeWindow(removalInfo, removalInfo.removeImmediately);
-        } else {
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
-                    "Task start finish, remove starting surface for task: %d",
-                    removalInfo.taskId);
-            mWindowRecords.removeWindow(removalInfo, removalInfo.removeImmediately);
-        }
-    }
-
-    /**
-     * Create a windowless starting surface and attach to the root surface.
-     */
-    void addWindowlessStartingSurface(StartingWindowInfo windowInfo) {
-        if (windowInfo.taskSnapshot != null) {
-            mWindowlessSnapshotWindowCreator.makeTaskSnapshotWindow(windowInfo,
-                    windowInfo.rootSurface, windowInfo.taskSnapshot, mSplashScreenExecutor);
-        } else {
-            mWindowlessSplashWindowCreator.addSplashScreenStartingWindow(
-                    windowInfo, windowInfo.rootSurface);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "Task start finish, remove starting surface for task: %d",
+                removalInfo.taskId);
+        removeWindowSynced(removalInfo, false /* immediately */);
     }
 
     /**
@@ -154,15 +419,37 @@
     public void clearAllWindows() {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
                 "Clear all starting windows immediately");
-        mWindowRecords.clearAllWindows();
-        mWindowlessRecords.clearAllWindows();
+        final int taskSize = mStartingWindowRecords.size();
+        final int[] taskIds = new int[taskSize];
+        for (int i = taskSize - 1; i >= 0; --i) {
+            taskIds[i] = mStartingWindowRecords.keyAt(i);
+        }
+        for (int i = taskSize - 1; i >= 0; --i) {
+            removeWindowNoAnimate(taskIds[i]);
+        }
     }
 
     /**
      * Called when the Task wants to copy the splash screen.
      */
     public void copySplashScreenView(int taskId) {
-        mSplashscreenWindowCreator.copySplashScreenView(taskId);
+        final StartingWindowRecord preView = mStartingWindowRecords.get(taskId);
+        SplashScreenViewParcelable parcelable;
+        SplashScreenView splashScreenView = preView != null ? preView.mContentView : null;
+        if (splashScreenView != null && splashScreenView.isCopyable()) {
+            parcelable = new SplashScreenViewParcelable(splashScreenView);
+            parcelable.setClientCallback(
+                    new RemoteCallback((bundle) -> mSplashScreenExecutor.execute(
+                            () -> onAppSplashScreenViewRemoved(taskId, false))));
+            splashScreenView.onCopied();
+            mAnimatedSplashScreenSurfaceHosts.append(taskId, splashScreenView.getSurfaceHost());
+        } else {
+            parcelable = null;
+        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "Copying splash screen window view for task: %d with parcelable %b",
+                taskId, parcelable != null);
+        ActivityTaskManager.getInstance().onSplashScreenViewCopyFinished(taskId, parcelable);
     }
 
     /**
@@ -172,148 +459,195 @@
      * @param taskId The Task id on which the splash screen was attached
      */
     public void onAppSplashScreenViewRemoved(int taskId) {
-        mSplashscreenWindowCreator.onAppSplashScreenViewRemoved(taskId);
+        onAppSplashScreenViewRemoved(taskId, true /* fromServer */);
+    }
+
+    /**
+     * @param fromServer If true, this means the removal was notified by the server. This is only
+     *                   used for debugging purposes.
+     * @see #onAppSplashScreenViewRemoved(int)
+     */
+    private void onAppSplashScreenViewRemoved(int taskId, boolean fromServer) {
+        SurfaceControlViewHost viewHost =
+                mAnimatedSplashScreenSurfaceHosts.get(taskId);
+        if (viewHost == null) {
+            return;
+        }
+        mAnimatedSplashScreenSurfaceHosts.remove(taskId);
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "%s the splash screen. Releasing SurfaceControlViewHost for task: %d",
+                fromServer ? "Server cleaned up" : "App removed", taskId);
+        SplashScreenView.releaseIconHost(viewHost);
+    }
+
+    protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,
+            WindowManager.LayoutParams params, @StartingWindowType int suggestType) {
+        boolean shouldSaveView = true;
+        final Context context = view.getContext();
+        try {
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
+            mWindowManagerGlobal.addView(view, params, display,
+                    null /* parentWindow */, context.getUserId());
+        } catch (WindowManager.BadTokenException e) {
+            // ignore
+            Slog.w(TAG, appToken + " already running, starting window not displayed. "
+                    + e.getMessage());
+            shouldSaveView = false;
+        } finally {
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+            if (view.getParent() == null) {
+                Slog.w(TAG, "view not successfully added to wm, removing view");
+                mWindowManagerGlobal.removeView(view, true /* immediate */);
+                shouldSaveView = false;
+            }
+        }
+        if (shouldSaveView) {
+            removeWindowNoAnimate(taskId);
+            saveSplashScreenRecord(appToken, taskId, view, suggestType);
+        }
+        return shouldSaveView;
+    }
+
+    @VisibleForTesting
+    void saveSplashScreenRecord(IBinder appToken, int taskId, View view,
+            @StartingWindowType int suggestType) {
+        final StartingWindowRecord tView = new StartingWindowRecord(appToken, view,
+                null/* TaskSnapshotWindow */, suggestType);
+        mStartingWindowRecords.put(taskId, tView);
+    }
+
+    private void removeWindowNoAnimate(int taskId) {
+        mTmpRemovalInfo.taskId = taskId;
+        removeWindowSynced(mTmpRemovalInfo, true /* immediately */);
     }
 
     void onImeDrawnOnTask(int taskId) {
-        onImeDrawnOnTask(mWindowRecords, taskId);
-        onImeDrawnOnTask(mWindowlessRecords, taskId);
-    }
-
-    private void onImeDrawnOnTask(StartingWindowRecordManager records, int taskId) {
-        final StartingSurfaceDrawer.StartingWindowRecord sRecord =
-                records.getRecord(taskId);
-        final SnapshotRecord record = sRecord instanceof SnapshotRecord
-                ? (SnapshotRecord) sRecord : null;
-        if (record != null && record.hasImeSurface()) {
-            records.removeWindow(taskId, true);
+        final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
+        if (record != null && record.mTaskSnapshotWindow != null
+                && record.mTaskSnapshotWindow.hasImeSurface()) {
+            removeWindowNoAnimate(taskId);
         }
     }
 
-    static class WindowlessStartingWindow extends WindowlessWindowManager {
-        SurfaceControl mChildSurface;
+    protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo, boolean immediately) {
+        final int taskId = removalInfo.taskId;
+        final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
+        if (record != null) {
+            if (record.mDecorView != null) {
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                        "Removing splash screen window for task: %d", taskId);
+                if (record.mContentView != null) {
+                    record.clearSystemBarColor();
+                    if (immediately
+                            || record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+                        removeWindowInner(record.mDecorView, false);
+                    } else {
+                        if (removalInfo.playRevealAnimation) {
+                            mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
+                                    removalInfo.windowAnimationLeash, removalInfo.mainFrame,
+                                    () -> removeWindowInner(record.mDecorView, true),
+                                    record.mCreateTime, removalInfo.roundedCornerRadius);
+                        } else {
+                            // the SplashScreenView has been copied to client, hide the view to skip
+                            // default exit animation
+                            removeWindowInner(record.mDecorView, true);
+                        }
+                    }
+                } else {
+                    // shouldn't happen
+                    Slog.e(TAG, "Found empty splash screen, remove!");
+                    removeWindowInner(record.mDecorView, false);
+                }
 
-        WindowlessStartingWindow(Configuration c, SurfaceControl rootSurface) {
-            super(c, rootSurface, null /* hostInputToken */);
-        }
-
-        @Override
-        protected SurfaceControl getParentSurface(IWindow window,
-                WindowManager.LayoutParams attrs) {
-            final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
-                    .setContainerLayer()
-                    .setName("Windowless window")
-                    .setHidden(false)
-                    .setParent(mRootSurface)
-                    .setCallsite("WindowlessStartingWindow#attachToParentSurface");
-            mChildSurface = builder.build();
-            try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
-                t.setLayer(mChildSurface, Integer.MAX_VALUE);
-                t.apply();
             }
-            return mChildSurface;
-        }
-    }
-    abstract static class StartingWindowRecord {
-        protected int mBGColor;
-        abstract void removeIfPossible(StartingWindowRemovalInfo info, boolean immediately);
-        int getBGColor() {
-            return mBGColor;
-        }
-    }
-
-    abstract static class SnapshotRecord extends StartingWindowRecord {
-        private static final long DELAY_REMOVAL_TIME_GENERAL = 100;
-        /**
-         * The max delay time in milliseconds for removing the task snapshot window with IME
-         * visible.
-         * Ideally the delay time will be shorter when receiving
-         * {@link StartingSurfaceDrawer#onImeDrawnOnTask(int)}.
-         */
-        private static final long MAX_DELAY_REMOVAL_TIME_IME_VISIBLE = 600;
-        private final Runnable mScheduledRunnable = this::removeImmediately;
-
-        @WindowConfiguration.ActivityType protected final int mActivityType;
-        protected final ShellExecutor mRemoveExecutor;
-
-        SnapshotRecord(int activityType, ShellExecutor removeExecutor) {
-            mActivityType = activityType;
-            mRemoveExecutor = removeExecutor;
-        }
-
-        @Override
-        public final void removeIfPossible(StartingWindowRemovalInfo info, boolean immediately) {
-            if (immediately) {
-                removeImmediately();
-            } else {
-                scheduleRemove(info.deferRemoveForIme);
+            if (record.mTaskSnapshotWindow != null) {
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                        "Removing task snapshot window for %d", taskId);
+                if (immediately) {
+                    record.mTaskSnapshotWindow.removeImmediately();
+                } else {
+                    record.mTaskSnapshotWindow.scheduleRemove(removalInfo.deferRemoveForIme);
+                }
             }
+            mStartingWindowRecords.remove(taskId);
+        }
+    }
+
+    private void removeWindowInner(View decorView, boolean hideView) {
+        if (mSysuiProxy != null) {
+            mSysuiProxy.requestTopUi(false, TAG);
+        }
+        if (hideView) {
+            decorView.setVisibility(View.GONE);
+        }
+        mWindowManagerGlobal.removeView(decorView, false /* immediate */);
+    }
+
+    /**
+     * Record the view or surface for a starting window.
+     */
+    private static class StartingWindowRecord {
+        private final IBinder mAppToken;
+        private final View mDecorView;
+        private final TaskSnapshotWindow mTaskSnapshotWindow;
+        private SplashScreenView mContentView;
+        private boolean mSetSplashScreen;
+        @StartingWindowType private int mSuggestType;
+        private int mBGColor;
+        private final long mCreateTime;
+        private int mSystemBarAppearance;
+        private boolean mDrawsSystemBarBackgrounds;
+
+        StartingWindowRecord(IBinder appToken, View decorView,
+                TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) {
+            mAppToken = appToken;
+            mDecorView = decorView;
+            mTaskSnapshotWindow = taskSnapshotWindow;
+            if (mTaskSnapshotWindow != null) {
+                mBGColor = mTaskSnapshotWindow.getBackgroundColor();
+            }
+            mSuggestType = suggestType;
+            mCreateTime = SystemClock.uptimeMillis();
         }
 
-        void scheduleRemove(boolean deferRemoveForIme) {
-            // Show the latest content as soon as possible for unlocking to home.
-            if (mActivityType == ACTIVITY_TYPE_HOME) {
-                removeImmediately();
+        private void setSplashScreenView(SplashScreenView splashScreenView) {
+            if (mSetSplashScreen) {
                 return;
             }
-            mRemoveExecutor.removeCallbacks(mScheduledRunnable);
-            final long delayRemovalTime = hasImeSurface() && deferRemoveForIme
-                    ? MAX_DELAY_REMOVAL_TIME_IME_VISIBLE
-                    : DELAY_REMOVAL_TIME_GENERAL;
-            mRemoveExecutor.executeDelayed(mScheduledRunnable, delayRemovalTime);
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
-                    "Defer removing snapshot surface in %d", delayRemovalTime);
+            mContentView = splashScreenView;
+            mSetSplashScreen = true;
         }
 
-        protected abstract boolean hasImeSurface();
-
-        @CallSuper
-        protected void removeImmediately() {
-            mRemoveExecutor.removeCallbacks(mScheduledRunnable);
-        }
-    }
-
-    static class StartingWindowRecordManager {
-        private final StartingWindowRemovalInfo mTmpRemovalInfo = new StartingWindowRemovalInfo();
-        private final SparseArray<StartingWindowRecord> mStartingWindowRecords =
-                new SparseArray<>();
-
-        void clearAllWindows() {
-            final int taskSize = mStartingWindowRecords.size();
-            final int[] taskIds = new int[taskSize];
-            for (int i = taskSize - 1; i >= 0; --i) {
-                taskIds[i] = mStartingWindowRecords.keyAt(i);
+        private void parseAppSystemBarColor(Context context) {
+            final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
+            mDrawsSystemBarBackgrounds = a.getBoolean(
+                    R.styleable.Window_windowDrawsSystemBarBackgrounds, false);
+            if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
+                mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
             }
-            for (int i = taskSize - 1; i >= 0; --i) {
-                removeWindow(taskIds[i], true);
+            if (a.getBoolean(R.styleable.Window_windowLightNavigationBar, false)) {
+                mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
             }
+            a.recycle();
         }
 
-        void addRecord(int taskId, StartingWindowRecord record) {
-            mStartingWindowRecords.put(taskId, record);
-        }
-
-        void removeWindow(StartingWindowRemovalInfo removeInfo, boolean immediately) {
-            final int taskId = removeInfo.taskId;
-            final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
-            if (record != null) {
-                record.removeIfPossible(removeInfo, immediately);
-                mStartingWindowRecords.remove(taskId);
+        // Reset the system bar color which set by splash screen, make it align to the app.
+        private void clearSystemBarColor() {
+            if (mDecorView == null || !mDecorView.isAttachedToWindow()) {
+                return;
             }
-        }
-
-        void removeWindow(int taskId, boolean immediately) {
-            mTmpRemovalInfo.taskId = taskId;
-            removeWindow(mTmpRemovalInfo, immediately);
-        }
-
-        StartingWindowRecord getRecord(int taskId) {
-            return mStartingWindowRecords.get(taskId);
-        }
-
-        @VisibleForTesting
-        int recordSize() {
-            return mStartingWindowRecords.size();
+            if (mDecorView.getLayoutParams() instanceof WindowManager.LayoutParams) {
+                final WindowManager.LayoutParams lp =
+                        (WindowManager.LayoutParams) mDecorView.getLayoutParams();
+                if (mDrawsSystemBarBackgrounds) {
+                    lp.flags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+                } else {
+                    lp.flags &= ~WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+                }
+                mDecorView.setLayoutParams(lp);
+            }
+            mDecorView.getWindowInsetsController().setSystemBarsAppearance(
+                    mSystemBarAppearance, LIGHT_BARS_MASK);
         }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
index bec4ba3..be2e793 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -21,7 +21,6 @@
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN;
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_WINDOWLESS;
 
 import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
 import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_STARTING_WINDOW;
@@ -30,6 +29,7 @@
 import android.app.TaskInfo;
 import android.content.Context;
 import android.graphics.Color;
+import android.os.IBinder;
 import android.os.Trace;
 import android.util.SparseIntArray;
 import android.window.StartingWindowInfo;
@@ -152,23 +152,22 @@
     /**
      * Called when a task need a starting window.
      */
-    public void addStartingWindow(StartingWindowInfo windowInfo) {
+    public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
         mSplashScreenExecutor.execute(() -> {
             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addStartingWindow");
 
             final int suggestionType = mStartingWindowTypeAlgorithm.getSuggestedWindowType(
                     windowInfo);
             final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
-            if (suggestionType == STARTING_WINDOW_TYPE_WINDOWLESS) {
-                mStartingSurfaceDrawer.addWindowlessStartingSurface(windowInfo);
-            } else if (isSplashScreenType(suggestionType)) {
-                mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, suggestionType);
+            if (isSplashScreenType(suggestionType)) {
+                mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
+                        suggestionType);
             } else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
                 final TaskSnapshot snapshot = windowInfo.taskSnapshot;
-                mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, snapshot);
+                mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken,
+                        snapshot);
             }
-            if (suggestionType != STARTING_WINDOW_TYPE_NONE
-                    && suggestionType != STARTING_WINDOW_TYPE_WINDOWLESS) {
+            if (suggestionType != STARTING_WINDOW_TYPE_NONE) {
                 int taskId = runningTaskInfo.taskId;
                 int color = mStartingSurfaceDrawer
                         .getStartingWindowBackgroundColorForTask(taskId);
@@ -219,13 +218,11 @@
     public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) {
         mSplashScreenExecutor.execute(() -> mStartingSurfaceDrawer.removeStartingWindow(
                 removalInfo));
-        if (!removalInfo.windowlessSurface) {
-            mSplashScreenExecutor.executeDelayed(() -> {
-                synchronized (mTaskBackgroundColors) {
-                    mTaskBackgroundColors.delete(removalInfo.taskId);
-                }
-            }, TASK_BG_COLOR_RETAIN_TIME_MS);
-        }
+        mSplashScreenExecutor.executeDelayed(() -> {
+            synchronized (mTaskBackgroundColors) {
+                mTaskBackgroundColors.delete(removalInfo.taskId);
+            }
+        }, TASK_BG_COLOR_RETAIN_TIME_MS);
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index c964df1..a05ed4f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.startingsurface;
 
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.graphics.Color.WHITE;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -62,14 +63,24 @@
     private static final String TAG = StartingWindowController.TAG;
     private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=";
 
+    private static final long DELAY_REMOVAL_TIME_GENERAL = 100;
+    /**
+     * The max delay time in milliseconds for removing the task snapshot window with IME visible.
+     * Ideally the delay time will be shorter when receiving
+     * {@link StartingSurfaceDrawer#onImeDrawnOnTask(int)}.
+     */
+    private static final long MAX_DELAY_REMOVAL_TIME_IME_VISIBLE = 600;
+
     private final Window mWindow;
     private final Runnable mClearWindowHandler;
     private final ShellExecutor mSplashScreenExecutor;
     private final IWindowSession mSession;
     private boolean mHasDrawn;
     private final Paint mBackgroundPaint = new Paint();
+    private final int mActivityType;
     private final int mOrientationOnCreation;
 
+    private final Runnable mScheduledRunnable = this::removeImmediately;
     private final boolean mHasImeSurface;
 
     static TaskSnapshotWindow create(StartingWindowInfo info, IBinder appToken,
@@ -93,6 +104,7 @@
         final Point taskSize = snapshot.getTaskSize();
         final Rect taskBounds = new Rect(0, 0, taskSize.x, taskSize.y);
         final int orientation = snapshot.getOrientation();
+        final int activityType = runningTaskInfo.topActivityType;
         final int displayId = runningTaskInfo.displayId;
 
         final IWindowSession session = WindowManagerGlobal.getWindowSession();
@@ -102,11 +114,16 @@
         final InsetsSourceControl.Array tmpControls = new InsetsSourceControl.Array();
         final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
 
-        final TaskDescription taskDescription =
-                SnapshotDrawerUtils.getOrCreateTaskDescription(runningTaskInfo);
+        final TaskDescription taskDescription;
+        if (runningTaskInfo.taskDescription != null) {
+            taskDescription = runningTaskInfo.taskDescription;
+        } else {
+            taskDescription = new TaskDescription();
+            taskDescription.setBackgroundColor(WHITE);
+        }
 
         final TaskSnapshotWindow snapshotSurface = new TaskSnapshotWindow(
-                snapshot, taskDescription, orientation,
+                snapshot, taskDescription, orientation, activityType,
                 clearWindowHandler, splashScreenExecutor);
         final Window window = snapshotSurface.mWindow;
 
@@ -136,8 +153,6 @@
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
         } catch (RemoteException e) {
             snapshotSurface.clearWindowSynced();
-            Slog.w(TAG, "Failed to relayout snapshot starting window");
-            return null;
         }
 
         SnapshotDrawerUtils.drawSnapshotOnSurface(info, layoutParams, surfaceControl, snapshot,
@@ -149,7 +164,7 @@
     }
 
     public TaskSnapshotWindow(TaskSnapshot snapshot, TaskDescription taskDescription,
-            int currentOrientation, Runnable clearWindowHandler,
+            int currentOrientation, int activityType, Runnable clearWindowHandler,
             ShellExecutor splashScreenExecutor) {
         mSplashScreenExecutor = splashScreenExecutor;
         mSession = WindowManagerGlobal.getWindowSession();
@@ -158,6 +173,7 @@
         int backgroundColor = taskDescription.getBackgroundColor();
         mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
         mOrientationOnCreation = currentOrientation;
+        mActivityType = activityType;
         mClearWindowHandler = clearWindowHandler;
         mHasImeSurface = snapshot.hasImeSurface();
     }
@@ -170,7 +186,23 @@
 	return mHasImeSurface;
     }
 
+    void scheduleRemove(boolean deferRemoveForIme) {
+        // Show the latest content as soon as possible for unlocking to home.
+        if (mActivityType == ACTIVITY_TYPE_HOME) {
+            removeImmediately();
+            return;
+        }
+        mSplashScreenExecutor.removeCallbacks(mScheduledRunnable);
+        final long delayRemovalTime = mHasImeSurface && deferRemoveForIme
+                ? MAX_DELAY_REMOVAL_TIME_IME_VISIBLE
+                : DELAY_REMOVAL_TIME_GENERAL;
+        mSplashScreenExecutor.executeDelayed(mScheduledRunnable, delayRemovalTime);
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "Defer removing snapshot surface in %d", delayRemovalTime);
+    }
+
     void removeImmediately() {
+        mSplashScreenExecutor.removeCallbacks(mScheduledRunnable);
         try {
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
                     "Removing taskSnapshot surface, mHasDrawn=%b", mHasDrawn);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
deleted file mode 100644
index 1445478..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
+++ /dev/null
@@ -1,165 +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.startingsurface;
-
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.view.Display;
-import android.view.InsetsState;
-import android.view.SurfaceControl;
-import android.view.SurfaceControlViewHost;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.window.SnapshotDrawerUtils;
-import android.window.StartingWindowInfo;
-import android.window.TaskSnapshot;
-
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.TransactionPool;
-
-class WindowlessSnapshotWindowCreator {
-    private static final int DEFAULT_FADEOUT_DURATION = 233;
-    private final StartingSurfaceDrawer.StartingWindowRecordManager
-            mStartingWindowRecordManager;
-    private final DisplayManager mDisplayManager;
-    private final Context mContext;
-    private final SplashscreenContentDrawer mSplashscreenContentDrawer;
-    private final TransactionPool mTransactionPool;
-
-    WindowlessSnapshotWindowCreator(
-            StartingSurfaceDrawer.StartingWindowRecordManager startingWindowRecordManager,
-            Context context,
-            DisplayManager displayManager, SplashscreenContentDrawer splashscreenContentDrawer,
-            TransactionPool transactionPool) {
-        mStartingWindowRecordManager = startingWindowRecordManager;
-        mContext = context;
-        mDisplayManager = displayManager;
-        mSplashscreenContentDrawer = splashscreenContentDrawer;
-        mTransactionPool = transactionPool;
-    }
-
-    void makeTaskSnapshotWindow(StartingWindowInfo info, SurfaceControl rootSurface,
-            TaskSnapshot snapshot, ShellExecutor removeExecutor) {
-        final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
-        final int taskId = runningTaskInfo.taskId;
-        final String title = "Windowless Snapshot " + taskId;
-        final WindowManager.LayoutParams lp = SnapshotDrawerUtils.createLayoutParameters(
-                info, title, TYPE_APPLICATION_OVERLAY, snapshot.getHardwareBuffer().getFormat(),
-                null /* token */);
-        if (lp == null) {
-            return;
-        }
-        final Display display = mDisplayManager.getDisplay(runningTaskInfo.displayId);
-        final StartingSurfaceDrawer.WindowlessStartingWindow wlw =
-                new StartingSurfaceDrawer.WindowlessStartingWindow(
-                runningTaskInfo.configuration, rootSurface);
-        final SurfaceControlViewHost mViewHost = new SurfaceControlViewHost(
-                mContext, display, wlw, "WindowlessSnapshotWindowCreator");
-        final Point taskSize = snapshot.getTaskSize();
-        final Rect snapshotBounds = new Rect(0, 0, taskSize.x, taskSize.y);
-        final Rect windowBounds = runningTaskInfo.configuration.windowConfiguration.getBounds();
-        final InsetsState topWindowInsetsState = info.topOpaqueWindowInsetsState;
-        final FrameLayout rootLayout = new FrameLayout(
-                mSplashscreenContentDrawer.createViewContextWrapper(mContext));
-        mViewHost.setView(rootLayout, lp);
-        SnapshotDrawerUtils.drawSnapshotOnSurface(info, lp, wlw.mChildSurface, snapshot,
-                snapshotBounds, windowBounds, topWindowInsetsState, false /* releaseAfterDraw */);
-
-        final ActivityManager.TaskDescription taskDescription =
-                SnapshotDrawerUtils.getOrCreateTaskDescription(runningTaskInfo);
-
-        final SnapshotWindowRecord record = new SnapshotWindowRecord(mViewHost, wlw.mChildSurface,
-                taskDescription.getBackgroundColor(), snapshot.hasImeSurface(),
-                runningTaskInfo.topActivityType, removeExecutor);
-        mStartingWindowRecordManager.addRecord(taskId, record);
-        info.notifyAddComplete(wlw.mChildSurface);
-    }
-
-    private class SnapshotWindowRecord extends StartingSurfaceDrawer.SnapshotRecord {
-        private SurfaceControlViewHost mViewHost;
-        private SurfaceControl mChildSurface;
-        private final boolean mHasImeSurface;
-
-        SnapshotWindowRecord(SurfaceControlViewHost viewHost, SurfaceControl childSurface,
-                int bgColor, boolean hasImeSurface, int activityType,
-                ShellExecutor removeExecutor) {
-            super(activityType, removeExecutor);
-            mViewHost = viewHost;
-            mChildSurface = childSurface;
-            mBGColor = bgColor;
-            mHasImeSurface = hasImeSurface;
-        }
-
-        @Override
-        protected void removeImmediately() {
-            super.removeImmediately();
-            fadeoutThenRelease();
-        }
-
-        void fadeoutThenRelease() {
-            final ValueAnimator fadeOutAnimator = ValueAnimator.ofFloat(1f, 0f);
-            fadeOutAnimator.setDuration(DEFAULT_FADEOUT_DURATION);
-            final SurfaceControl.Transaction t = mTransactionPool.acquire();
-            fadeOutAnimator.addUpdateListener(animation -> {
-                if (mChildSurface == null || !mChildSurface.isValid()) {
-                    fadeOutAnimator.cancel();
-                    return;
-                }
-                t.setAlpha(mChildSurface, (float) animation.getAnimatedValue());
-                t.apply();
-            });
-
-            fadeOutAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    if (mChildSurface == null || !mChildSurface.isValid()) {
-                        fadeOutAnimator.cancel();
-                    }
-                }
-
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mTransactionPool.release(t);
-                    if (mChildSurface != null) {
-                        final SurfaceControl.Transaction t = mTransactionPool.acquire();
-                        t.remove(mChildSurface).apply();
-                        mTransactionPool.release(t);
-                        mChildSurface = null;
-                    }
-                    if (mViewHost != null) {
-                        mViewHost.release();
-                        mViewHost = null;
-                    }
-                }
-            });
-            fadeOutAnimator.start();
-        }
-
-        @Override
-        protected boolean hasImeSurface() {
-            return mHasImeSurface;
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java
deleted file mode 100644
index 12a0d40..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSplashWindowCreator.java
+++ /dev/null
@@ -1,150 +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.startingsurface;
-
-import static android.graphics.Color.WHITE;
-import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.os.Binder;
-import android.os.SystemClock;
-import android.view.Display;
-import android.view.SurfaceControl;
-import android.view.SurfaceControlViewHost;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.window.SplashScreenView;
-import android.window.StartingWindowInfo;
-import android.window.StartingWindowRemovalInfo;
-
-import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.TransactionPool;
-
-class WindowlessSplashWindowCreator extends AbsSplashWindowCreator {
-
-    private final TransactionPool mTransactionPool;
-
-    WindowlessSplashWindowCreator(SplashscreenContentDrawer contentDrawer,
-            Context context,
-            ShellExecutor splashScreenExecutor,
-            DisplayManager displayManager,
-            StartingSurfaceDrawer.StartingWindowRecordManager startingWindowRecordManager,
-            TransactionPool pool) {
-        super(contentDrawer, context, splashScreenExecutor, displayManager,
-                startingWindowRecordManager);
-        mTransactionPool = pool;
-    }
-
-    void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, SurfaceControl rootSurface) {
-        final ActivityManager.RunningTaskInfo taskInfo = windowInfo.taskInfo;
-        final ActivityInfo activityInfo = windowInfo.targetActivityInfo != null
-                ? windowInfo.targetActivityInfo
-                : taskInfo.topActivityInfo;
-        if (activityInfo == null || activityInfo.packageName == null) {
-            return;
-        }
-
-        final int displayId = taskInfo.displayId;
-        final Display display = mDisplayManager.getDisplay(displayId);
-        if (display == null) {
-            // Can't show splash screen on requested display, so skip showing at all.
-            return;
-        }
-        final Context myContext = SplashscreenContentDrawer.createContext(mContext, windowInfo,
-                0 /* theme */, STARTING_WINDOW_TYPE_SPLASH_SCREEN, mDisplayManager);
-        if (myContext == null) {
-            return;
-        }
-        final StartingSurfaceDrawer.WindowlessStartingWindow wlw =
-                new StartingSurfaceDrawer.WindowlessStartingWindow(
-                        taskInfo.configuration, rootSurface);
-        final SurfaceControlViewHost viewHost = new SurfaceControlViewHost(
-                myContext, display, wlw, "WindowlessSplashWindowCreator");
-        final String title = "Windowless Splash " + taskInfo.taskId;
-        final WindowManager.LayoutParams lp = SplashscreenContentDrawer.createLayoutParameters(
-                myContext, windowInfo, STARTING_WINDOW_TYPE_SPLASH_SCREEN, title,
-                PixelFormat.TRANSLUCENT, new Binder());
-        final Rect windowBounds = taskInfo.configuration.windowConfiguration.getBounds();
-        lp.width = windowBounds.width();
-        lp.height = windowBounds.height();
-        final ActivityManager.TaskDescription taskDescription;
-        if (taskInfo.taskDescription != null) {
-            taskDescription = taskInfo.taskDescription;
-        } else {
-            taskDescription = new ActivityManager.TaskDescription();
-            taskDescription.setBackgroundColor(WHITE);
-        }
-
-        final FrameLayout rootLayout = new FrameLayout(
-                mSplashscreenContentDrawer.createViewContextWrapper(mContext));
-        viewHost.setView(rootLayout, lp);
-
-        final int bgColor = taskDescription.getBackgroundColor();
-        final SplashScreenView splashScreenView = mSplashscreenContentDrawer
-                .makeSimpleSplashScreenContentView(myContext, windowInfo, bgColor);
-        rootLayout.addView(splashScreenView);
-        final SplashWindowRecord record = new SplashWindowRecord(viewHost, splashScreenView,
-                wlw.mChildSurface, bgColor);
-        mStartingWindowRecordManager.addRecord(taskInfo.taskId, record);
-        windowInfo.notifyAddComplete(wlw.mChildSurface);
-    }
-
-    private class SplashWindowRecord extends StartingSurfaceDrawer.StartingWindowRecord {
-        private SurfaceControlViewHost mViewHost;
-        private final long mCreateTime;
-        private SurfaceControl mChildSurface;
-        private final SplashScreenView mSplashView;
-
-        SplashWindowRecord(SurfaceControlViewHost viewHost, SplashScreenView splashView,
-                SurfaceControl childSurface, int bgColor) {
-            mViewHost = viewHost;
-            mSplashView = splashView;
-            mChildSurface = childSurface;
-            mBGColor = bgColor;
-            mCreateTime = SystemClock.uptimeMillis();
-        }
-
-        @Override
-        public void removeIfPossible(StartingWindowRemovalInfo info, boolean immediately) {
-            if (!immediately) {
-                mSplashscreenContentDrawer.applyExitAnimation(mSplashView,
-                        info.windowAnimationLeash, info.mainFrame,
-                        this::release, mCreateTime, 0 /* roundedCornerRadius */);
-            } else {
-                release();
-            }
-        }
-
-        void release() {
-            if (mChildSurface != null) {
-                final SurfaceControl.Transaction t = mTransactionPool.acquire();
-                t.remove(mChildSurface).apply();
-                mTransactionPool.release(t);
-                mChildSurface = null;
-            }
-            if (mViewHost != null) {
-                mViewHost.release();
-                mViewHost = null;
-            }
-        }
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
index 72fc8686..bb43d7c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
@@ -22,7 +22,6 @@
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SOLID_COLOR_SPLASH_SCREEN;
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
-import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_WINDOWLESS;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_DRAWN;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
@@ -31,7 +30,6 @@
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_USE_SOLID_COLOR_SPLASH_SCREEN;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_WINDOWLESS;
 
 import android.window.StartingWindowInfo;
 
@@ -57,7 +55,6 @@
         final boolean legacySplashScreen =
                 ((parameter & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN) != 0);
         final boolean activityDrawn = (parameter & TYPE_PARAMETER_ACTIVITY_DRAWN) != 0;
-        final boolean windowlessSurface = (parameter & TYPE_PARAMETER_WINDOWLESS) != 0;
         final boolean topIsHome = windowInfo.taskInfo.topActivityType == ACTIVITY_TYPE_HOME;
 
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
@@ -70,15 +67,10 @@
                         + "isSolidColorSplashScreen=%b, "
                         + "legacySplashScreen=%b, "
                         + "activityDrawn=%b, "
-                        + "windowless=%b, "
                         + "topIsHome=%b",
                 newTask, taskSwitch, processRunning, allowTaskSnapshot, activityCreated,
-                isSolidColorSplashScreen, legacySplashScreen, activityDrawn, windowlessSurface,
-                topIsHome);
+                isSolidColorSplashScreen, legacySplashScreen, activityDrawn, topIsHome);
 
-        if (windowlessSurface) {
-            return STARTING_WINDOW_TYPE_WINDOWLESS;
-        }
         if (!topIsHome) {
             if (!processRunning || newTask || (taskSwitch && !activityCreated)) {
                 return getSplashscreenType(isSolidColorSplashScreen, legacySplashScreen);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java
index 19133e2..628ce27 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/CounterRotatorHelper.java
@@ -28,6 +28,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.wm.shell.util.CounterRotator;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.List;
 
@@ -57,7 +58,7 @@
         for (int i = numChanges - 1; i >= 0; --i) {
             final TransitionInfo.Change change = changes.get(i);
             final WindowContainerToken parent = change.getParent();
-            if (!Transitions.isClosingType(change.getMode())
+            if (!TransitionUtil.isClosingType(change.getMode())
                     || !TransitionInfo.isIndependent(change, info) || parent == null) {
                 continue;
             }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 8e916e6..ef405c8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -44,6 +44,7 @@
 import com.android.wm.shell.splitscreen.SplitScreenController;
 import com.android.wm.shell.splitscreen.StageCoordinator;
 import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.ArrayList;
 import java.util.Optional;
@@ -149,7 +150,7 @@
             mSplitHandler.addEnterOrExitIfNeeded(request, out);
             return out;
         } else if (request.getRemoteTransition() != null
-                && Transitions.isOpeningType(request.getType())
+                && TransitionUtil.isOpeningType(request.getType())
                 && (request.getTriggerTask() == null
                 || (request.getTriggerTask().topActivityType != ACTIVITY_TYPE_HOME
                         && request.getTriggerTask().topActivityType != ACTIVITY_TYPE_RECENTS))) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index a3e05f2..f66c26b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -112,6 +112,7 @@
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.sysui.ShellInit;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -445,7 +446,7 @@
                         backgroundColorForTransition);
 
                 if (!isTask && a.hasExtension()) {
-                    if (!Transitions.isOpeningType(change.getMode())) {
+                    if (!TransitionUtil.isOpeningType(change.getMode())) {
                         // Can screenshot now (before startTransaction is applied)
                         edgeExtendWindow(change, a, startTransaction, finishTransaction);
                     } else {
@@ -456,7 +457,7 @@
                     }
                 }
 
-                final Rect clipRect = Transitions.isClosingType(change.getMode())
+                final Rect clipRect = TransitionUtil.isClosingType(change.getMode())
                         ? new Rect(mRotator.getEndBoundsInStartRotation(change))
                         : new Rect(change.getEndAbsBounds());
                 clipRect.offsetTo(0, 0);
@@ -562,12 +563,12 @@
         final int flags = info.getFlags();
         final int changeMode = change.getMode();
         final int changeFlags = change.getFlags();
-        final boolean isOpeningType = Transitions.isOpeningType(type);
-        final boolean enter = Transitions.isOpeningType(changeMode);
+        final boolean isOpeningType = TransitionUtil.isOpeningType(type);
+        final boolean enter = TransitionUtil.isOpeningType(changeMode);
         final boolean isTask = change.getTaskInfo() != null;
         final TransitionInfo.AnimationOptions options = info.getAnimationOptions();
         final int overrideType = options != null ? options.getType() : ANIM_NONE;
-        final Rect endBounds = Transitions.isClosingType(changeMode)
+        final Rect endBounds = TransitionUtil.isClosingType(changeMode)
                 ? mRotator.getEndBoundsInStartRotation(change)
                 : change.getEndAbsBounds();
 
@@ -689,8 +690,8 @@
     private void attachThumbnail(@NonNull ArrayList<Animator> animations,
             @NonNull Runnable finishCallback, TransitionInfo.Change change,
             TransitionInfo.AnimationOptions options, float cornerRadius) {
-        final boolean isOpen = Transitions.isOpeningType(change.getMode());
-        final boolean isClose = Transitions.isClosingType(change.getMode());
+        final boolean isOpen = TransitionUtil.isOpeningType(change.getMode());
+        final boolean isClose = TransitionUtil.isClosingType(change.getMode());
         if (isOpen) {
             if (options.getType() == ANIM_OPEN_CROSS_PROFILE_APPS) {
                 attachCrossProfileThumbnailAnimation(animations, finishCallback, change,
@@ -772,16 +773,16 @@
         for (int i = info.getChanges().size() - 1; i >= 0; --i) {
             final TransitionInfo.Change change = info.getChanges().get(i);
             if ((change.getFlags() & FLAG_SHOW_WALLPAPER) != 0) {
-                if (Transitions.isOpeningType(change.getMode())) {
+                if (TransitionUtil.isOpeningType(change.getMode())) {
                     hasOpenWallpaper = true;
-                } else if (Transitions.isClosingType(change.getMode())) {
+                } else if (TransitionUtil.isClosingType(change.getMode())) {
                     hasCloseWallpaper = true;
                 }
             }
         }
 
         if (hasOpenWallpaper && hasCloseWallpaper) {
-            return Transitions.isOpeningType(info.getType())
+            return TransitionUtil.isOpeningType(info.getType())
                     ? WALLPAPER_TRANSITION_INTRA_OPEN : WALLPAPER_TRANSITION_INTRA_CLOSE;
         } else if (hasOpenWallpaper) {
             return WALLPAPER_TRANSITION_OPEN;
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 02f19eb..3c4e889 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
@@ -39,6 +39,7 @@
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.ArrayList;
 
@@ -93,7 +94,7 @@
             @NonNull SurfaceControl.Transaction startTransaction,
             @NonNull SurfaceControl.Transaction finishTransaction,
             @NonNull Transitions.TransitionFinishCallback finishCallback) {
-        if (!Transitions.SHELL_TRANSITIONS_ROTATION && Transitions.hasDisplayChange(info)) {
+        if (!Transitions.SHELL_TRANSITIONS_ROTATION && TransitionUtil.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;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
index 5a5ceab..8d29901 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java
@@ -54,6 +54,7 @@
 import com.android.internal.policy.TransitionAnimation;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
+import com.android.wm.shell.util.TransitionUtil;
 
 /** The helper class that provides methods for adding styles to transition animations. */
 public class TransitionAnimationHelper {
@@ -66,7 +67,7 @@
         final int type = info.getType();
         final int changeMode = change.getMode();
         final int changeFlags = change.getFlags();
-        final boolean enter = Transitions.isOpeningType(changeMode);
+        final boolean enter = TransitionUtil.isOpeningType(changeMode);
         final boolean isTask = change.getTaskInfo() != null;
         final TransitionInfo.AnimationOptions options = info.getAnimationOptions();
         final int overrideType = options != null ? options.getType() : ANIM_NONE;
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 0a67477..3b154d1 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
@@ -19,13 +19,11 @@
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FIRST_CUSTOM;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.view.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;
@@ -33,6 +31,8 @@
 
 import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
 import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
+import static com.android.wm.shell.util.TransitionUtil.isClosingType;
+import static com.android.wm.shell.util.TransitionUtil.isOpeningType;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -319,29 +319,6 @@
         }
     }
 
-    /** @return true if the transition was triggered by opening something vs closing something */
-    public static boolean isOpeningType(@WindowManager.TransitionType int type) {
-        return type == TRANSIT_OPEN
-                || type == TRANSIT_TO_FRONT
-                || type == TRANSIT_KEYGUARD_GOING_AWAY;
-    }
-
-    /** @return true if the transition was triggered by closing something vs opening something */
-    public static boolean isClosingType(@WindowManager.TransitionType int type) {
-        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/util/TransitionUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
new file mode 100644
index 0000000..145f759
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.util;
+
+import static android.view.WindowManager.TRANSIT_CHANGE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
+
+import android.annotation.NonNull;
+import android.view.WindowManager;
+import android.window.TransitionInfo;
+
+/** Various utility functions for transitions. */
+public class TransitionUtil {
+
+    /** @return true if the transition was triggered by opening something vs closing something */
+    public static boolean isOpeningType(@WindowManager.TransitionType int type) {
+        return type == TRANSIT_OPEN
+                || type == TRANSIT_TO_FRONT
+                || type == TRANSIT_KEYGUARD_GOING_AWAY;
+    }
+
+    /** @return true if the transition was triggered by closing something vs opening something */
+    public static boolean isClosingType(@WindowManager.TransitionType int type) {
+        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;
+    }
+
+}
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 766c4cd..2aa6d12 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
@@ -20,10 +20,14 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 
+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 android.app.ActivityManager;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityTaskManager;
 import android.content.Context;
+import android.graphics.Rect;
 import android.hardware.input.InputManager;
 import android.os.Handler;
 import android.os.Looper;
@@ -37,7 +41,6 @@
 import android.view.SurfaceControl;
 import android.view.View;
 import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
 
 import androidx.annotation.Nullable;
 
@@ -50,6 +53,7 @@
 import com.android.wm.shell.desktopmode.DesktopModeStatus;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
 import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.splitscreen.SplitScreenController;
 
 import java.util.Optional;
 
@@ -80,6 +84,8 @@
     private final InputMonitorFactory mInputMonitorFactory;
     private TaskOperations mTaskOperations;
 
+    private Optional<SplitScreenController> mSplitScreenController;
+
     public DesktopModeWindowDecorViewModel(
             Context context,
             Handler mainHandler,
@@ -88,7 +94,8 @@
             DisplayController displayController,
             SyncTransactionQueue syncQueue,
             Optional<DesktopModeController> desktopModeController,
-            Optional<DesktopTasksController> desktopTasksController) {
+            Optional<DesktopTasksController> desktopTasksController,
+            Optional<SplitScreenController> splitScreenController) {
         this(
                 context,
                 mainHandler,
@@ -98,6 +105,7 @@
                 syncQueue,
                 desktopModeController,
                 desktopTasksController,
+                splitScreenController,
                 new DesktopModeWindowDecoration.Factory(),
                 new InputMonitorFactory());
     }
@@ -112,6 +120,7 @@
             SyncTransactionQueue syncQueue,
             Optional<DesktopModeController> desktopModeController,
             Optional<DesktopTasksController> desktopTasksController,
+            Optional<SplitScreenController> splitScreenController,
             DesktopModeWindowDecoration.Factory desktopModeWindowDecorFactory,
             InputMonitorFactory inputMonitorFactory) {
         mContext = context;
@@ -120,6 +129,7 @@
         mActivityTaskManager = mContext.getSystemService(ActivityTaskManager.class);
         mTaskOrganizer = taskOrganizer;
         mDisplayController = displayController;
+        mSplitScreenController = splitScreenController;
         mSyncQueue = syncQueue;
         mDesktopModeController = desktopModeController;
         mDesktopTasksController = desktopTasksController;
@@ -230,6 +240,15 @@
             final int id = v.getId();
             if (id == R.id.close_window || id == R.id.close_button) {
                 mTaskOperations.closeTask(mTaskToken);
+                if (mSplitScreenController.isPresent()
+                        && mSplitScreenController.get().isSplitScreenVisible()) {
+                    int remainingTaskPosition = mTaskId == mSplitScreenController.get()
+                            .getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT).taskId
+                            ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
+                    ActivityManager.RunningTaskInfo remainingTask = mSplitScreenController.get()
+                            .getTaskInfo(remainingTaskPosition);
+                    mSplitScreenController.get().moveTaskToFullscreen(remainingTask.taskId);
+                }
             } else if (id == R.id.back_button) {
                 mTaskOperations.injectBackKey();
             } else if (id == R.id.caption_handle) {
@@ -261,9 +280,6 @@
                     if (taskInfo.isFocused) {
                         return mDragDetector.isDragEvent();
                     }
-                    final WindowContainerTransaction wct = new WindowContainerTransaction();
-                    wct.reorder(mTaskToken, true /* onTop */);
-                    mSyncQueue.queue(wct);
                     return false;
                 case MotionEvent.ACTION_UP:
                 case MotionEvent.ACTION_CANCEL:
@@ -401,14 +417,14 @@
      * @param ev the {@link MotionEvent} received by {@link EventReceiver}
      */
     private void handleReceivedMotionEvent(MotionEvent ev, InputMonitor inputMonitor) {
+        final DesktopModeWindowDecoration relevantDecor = getRelevantWindowDecor(ev);
         if (DesktopModeStatus.isProto2Enabled()) {
-            final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
-            if (focusedDecor == null
-                    || focusedDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
-                handleCaptionThroughStatusBar(ev);
+            if (relevantDecor == null
+                    || relevantDecor.mTaskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
+                handleCaptionThroughStatusBar(ev, relevantDecor);
             }
         }
-        handleEventOutsideFocusedCaption(ev);
+        handleEventOutsideFocusedCaption(ev, relevantDecor);
         // Prevent status bar from reacting to a caption drag.
         if (DesktopModeStatus.isProto2Enabled()) {
             if (mTransitionDragActive) {
@@ -422,16 +438,16 @@
     }
 
     // If an UP/CANCEL action is received outside of caption bounds, turn off handle menu
-    private void handleEventOutsideFocusedCaption(MotionEvent ev) {
+    private void handleEventOutsideFocusedCaption(MotionEvent ev,
+            DesktopModeWindowDecoration relevantDecor) {
         final int action = ev.getActionMasked();
         if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
-            final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
-            if (focusedDecor == null) {
+            if (relevantDecor == null) {
                 return;
             }
 
             if (!mTransitionDragActive) {
-                focusedDecor.closeHandleMenuIfNeeded(ev);
+                relevantDecor.closeHandleMenuIfNeeded(ev);
             }
         }
     }
@@ -441,39 +457,38 @@
      * Perform caption actions if not able to through normal means.
      * Turn on desktop mode if handle is dragged below status bar.
      */
-    private void handleCaptionThroughStatusBar(MotionEvent ev) {
+    private void handleCaptionThroughStatusBar(MotionEvent ev,
+            DesktopModeWindowDecoration relevantDecor) {
         switch (ev.getActionMasked()) {
             case MotionEvent.ACTION_DOWN: {
                 // Begin drag through status bar if applicable.
-                final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
-                if (focusedDecor != null) {
+                if (relevantDecor != null) {
                     boolean dragFromStatusBarAllowed = false;
                     if (DesktopModeStatus.isProto2Enabled()) {
                         // In proto2 any full screen task can be dragged to freeform
-                        dragFromStatusBarAllowed = focusedDecor.mTaskInfo.getWindowingMode()
+                        dragFromStatusBarAllowed = relevantDecor.mTaskInfo.getWindowingMode()
                                 == WINDOWING_MODE_FULLSCREEN;
                     }
 
-                    if (dragFromStatusBarAllowed && focusedDecor.checkTouchEventInHandle(ev)) {
+                    if (dragFromStatusBarAllowed && relevantDecor.checkTouchEventInHandle(ev)) {
                         mTransitionDragActive = true;
                     }
                 }
                 break;
             }
             case MotionEvent.ACTION_UP: {
-                final DesktopModeWindowDecoration focusedDecor = getFocusedDecor();
-                if (focusedDecor == null) {
+                if (relevantDecor == null) {
                     mTransitionDragActive = false;
                     return;
                 }
                 if (mTransitionDragActive) {
                     mTransitionDragActive = false;
                     final int statusBarHeight = mDisplayController
-                            .getDisplayLayout(focusedDecor.mTaskInfo.displayId).stableInsets().top;
+                            .getDisplayLayout(relevantDecor.mTaskInfo.displayId).stableInsets().top;
                     if (ev.getY() > statusBarHeight) {
                         if (DesktopModeStatus.isProto2Enabled()) {
                             mDesktopTasksController.ifPresent(
-                                    c -> c.moveToDesktop(focusedDecor.mTaskInfo));
+                                    c -> c.moveToDesktop(relevantDecor.mTaskInfo));
                         } else if (DesktopModeStatus.isProto1Enabled()) {
                             mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
                         }
@@ -481,7 +496,7 @@
                         return;
                     }
                 }
-                focusedDecor.checkClickEvent(ev);
+                relevantDecor.checkClickEvent(ev);
                 break;
             }
             case MotionEvent.ACTION_CANCEL: {
@@ -491,6 +506,38 @@
     }
 
     @Nullable
+    private DesktopModeWindowDecoration getRelevantWindowDecor(MotionEvent ev) {
+        if (mSplitScreenController.isPresent()
+                && mSplitScreenController.get().isSplitScreenVisible()) {
+            // We can't look at focused task here as only one task will have focus.
+            return getSplitScreenDecor(ev);
+        } else {
+            return getFocusedDecor();
+        }
+    }
+
+    @Nullable
+    private DesktopModeWindowDecoration getSplitScreenDecor(MotionEvent ev) {
+        ActivityManager.RunningTaskInfo topOrLeftTask =
+                mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_TOP_OR_LEFT);
+        ActivityManager.RunningTaskInfo bottomOrRightTask =
+                mSplitScreenController.get().getTaskInfo(SPLIT_POSITION_BOTTOM_OR_RIGHT);
+        if (topOrLeftTask != null && topOrLeftTask.getConfiguration()
+                .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
+            return mWindowDecorByTaskId.get(topOrLeftTask.taskId);
+        } else if (bottomOrRightTask != null && bottomOrRightTask.getConfiguration()
+                .windowConfiguration.getBounds().contains((int) ev.getX(), (int) ev.getY())) {
+            Rect bottomOrRightBounds = bottomOrRightTask.getConfiguration().windowConfiguration
+                    .getBounds();
+            ev.offsetLocation(-bottomOrRightBounds.left, -bottomOrRightBounds.top);
+            return mWindowDecorByTaskId.get(bottomOrRightTask.taskId);
+        } else {
+            return null;
+        }
+
+    }
+
+    @Nullable
     private DesktopModeWindowDecoration getFocusedDecor() {
         final int size = mWindowDecorByTaskId.size();
         DesktopModeWindowDecoration focusedDecor = null;
diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp
index d6adaa7..b6696c7 100644
--- a/libs/WindowManager/Shell/tests/flicker/Android.bp
+++ b/libs/WindowManager/Shell/tests/flicker/Android.bp
@@ -41,6 +41,8 @@
     static_libs: [
         "androidx.test.ext.junit",
         "flickerlib",
+        "flickerlib-apphelpers",
+        "flickerlib-helpers",
         "truth-prebuilt",
         "app-helpers-core",
         "launcher-helper-lib",
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
index 65923ff..67ca9a1 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
@@ -24,7 +24,11 @@
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />
+        <option name="run-command" value="settings put system show_touches 1" />
+        <option name="run-command" value="settings put system pointer_location 1" />
         <option name="teardown-command" value="settings delete secure show_ime_with_hard_keyboard" />
+        <option name="teardown-command" value="settings delete system show_touches" />
+        <option name="teardown-command" value="settings delete system pointer_location" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true"/>
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 aafd7ed..c5ee7b7 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
@@ -18,12 +18,13 @@
 
 import android.app.Instrumentation
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerBuilderProvider
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.launcher3.tapl.LauncherInstrumentation
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.entireScreenCovered
-import com.android.server.wm.flicker.junit.FlickerBuilderProvider
 import com.android.server.wm.flicker.navBarLayerIsVisibleAtStartAndEnd
 import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd
 import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -32,7 +33,6 @@
 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.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 bd18108..ed93045 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
@@ -18,13 +18,13 @@
 
 package com.android.wm.shell.flicker
 
-import com.android.server.wm.flicker.FlickerTest
-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.component.matchers.IComponentMatcher
-import com.android.server.wm.traces.common.region.Region
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.common.datatypes.Region
+import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.common.flicker.subject.layers.LayerTraceEntrySubject
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.helpers.WindowUtils
 
 fun FlickerTest.appPairsDividerIsVisibleAtEnd() {
     assertLayersEnd { this.isVisible(APP_PAIR_SPLIT_DIVIDER_COMPONENT) }
@@ -247,7 +247,7 @@
     component: IComponentMatcher,
     landscapePosLeft: Boolean,
     portraitPosTop: Boolean,
-    rotation: PlatformConsts.Rotation
+    rotation: Rotation
 ): LayersTraceSubject {
     return invoke("splitAppLayerBoundsSnapToDivider") {
         it.splitAppLayerBoundsSnapToDivider(component, landscapePosLeft, portraitPosTop, rotation)
@@ -258,11 +258,13 @@
     component: IComponentMatcher,
     landscapePosLeft: Boolean,
     portraitPosTop: Boolean,
-    rotation: PlatformConsts.Rotation
+    rotation: Rotation
 ): LayerTraceEntrySubject {
     val displayBounds = WindowUtils.getDisplayBounds(rotation)
     return invoke {
-        val dividerRegion = layer(SPLIT_SCREEN_DIVIDER_COMPONENT).visibleRegion.region
+        val dividerRegion =
+            layer(SPLIT_SCREEN_DIVIDER_COMPONENT)?.visibleRegion?.region
+                ?: error("$SPLIT_SCREEN_DIVIDER_COMPONENT component not found")
         visibleRegion(component)
             .coversAtMost(
                 if (displayBounds.width > displayBounds.height) {
@@ -367,46 +369,54 @@
 }
 
 fun FlickerTest.appPairsPrimaryBoundsIsVisibleAtEnd(
-    rotation: PlatformConsts.Rotation,
+    rotation: Rotation,
     primaryComponent: IComponentMatcher
 ) {
     assertLayersEnd {
-        val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
+        val dividerRegion =
+            layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT)?.visibleRegion?.region
+                ?: error("$APP_PAIR_SPLIT_DIVIDER_COMPONENT component not found")
         visibleRegion(primaryComponent).overlaps(getPrimaryRegion(dividerRegion, rotation))
     }
 }
 
 fun FlickerTest.dockedStackPrimaryBoundsIsVisibleAtEnd(
-    rotation: PlatformConsts.Rotation,
+    rotation: Rotation,
     primaryComponent: IComponentMatcher
 ) {
     assertLayersEnd {
-        val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
+        val dividerRegion =
+            layer(DOCKED_STACK_DIVIDER_COMPONENT)?.visibleRegion?.region
+                ?: error("$DOCKED_STACK_DIVIDER_COMPONENT component not found")
         visibleRegion(primaryComponent).overlaps(getPrimaryRegion(dividerRegion, rotation))
     }
 }
 
 fun FlickerTest.appPairsSecondaryBoundsIsVisibleAtEnd(
-    rotation: PlatformConsts.Rotation,
+    rotation: Rotation,
     secondaryComponent: IComponentMatcher
 ) {
     assertLayersEnd {
-        val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
+        val dividerRegion =
+            layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT)?.visibleRegion?.region
+                ?: error("$APP_PAIR_SPLIT_DIVIDER_COMPONENT component not found")
         visibleRegion(secondaryComponent).overlaps(getSecondaryRegion(dividerRegion, rotation))
     }
 }
 
 fun FlickerTest.dockedStackSecondaryBoundsIsVisibleAtEnd(
-    rotation: PlatformConsts.Rotation,
+    rotation: Rotation,
     secondaryComponent: IComponentMatcher
 ) {
     assertLayersEnd {
-        val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
+        val dividerRegion =
+            layer(DOCKED_STACK_DIVIDER_COMPONENT)?.visibleRegion?.region
+                ?: error("$DOCKED_STACK_DIVIDER_COMPONENT component not found")
         visibleRegion(secondaryComponent).overlaps(getSecondaryRegion(dividerRegion, rotation))
     }
 }
 
-fun getPrimaryRegion(dividerRegion: Region, rotation: PlatformConsts.Rotation): Region {
+fun getPrimaryRegion(dividerRegion: Region, rotation: Rotation): Region {
     val displayBounds = WindowUtils.getDisplayBounds(rotation)
     return if (rotation.isRotated()) {
         Region.from(
@@ -425,7 +435,7 @@
     }
 }
 
-fun getSecondaryRegion(dividerRegion: Region, rotation: PlatformConsts.Rotation): Region {
+fun getSecondaryRegion(dividerRegion: Region, rotation: Rotation): Region {
     val displayBounds = WindowUtils.getDisplayBounds(rotation)
     return if (rotation.isRotated()) {
         Region.from(
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 e9c805e..983640a 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.component.matchers.ComponentNameMatcher
+import android.tools.common.datatypes.component.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/BaseBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
index 996b677..bab81d7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
@@ -21,16 +21,16 @@
 import android.content.Context
 import android.content.pm.PackageManager
 import android.os.ServiceManager
+import android.tools.common.Rotation
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.legacy.IFlickerTestData
+import android.tools.device.helpers.SYSTEMUI_PACKAGE
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.UiObject2
 import androidx.test.uiautomator.Until
-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.IFlickerTestData
 import com.android.server.wm.flicker.helpers.LaunchBubbleHelper
-import com.android.server.wm.flicker.helpers.SYSTEMUI_PACKAGE
-import com.android.server.wm.traces.common.service.PlatformConsts
 import com.android.wm.shell.flicker.BaseTest
 import org.junit.runners.Parameterized
 
@@ -89,7 +89,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt
index 7358da3..d0bca13 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTest.kt
@@ -18,14 +18,14 @@
 
 import android.os.SystemClock
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.UiObject2
 import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.Assume
 import org.junit.Before
 import org.junit.Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt
index 1a0fbe4..bdfdad5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.wm.shell.flicker.bubble
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt
index cf696c8..5e85eb8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ChangeActiveActivityFromBubbleTestShellTransit.kt
@@ -17,10 +17,10 @@
 package com.android.wm.shell.flicker.bubble
 
 import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.Assume
 import org.junit.Before
 import org.junit.runner.RunWith
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
index 9367a8a..8474ce0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTest.kt
@@ -19,14 +19,14 @@
 import android.content.Context
 import android.graphics.Point
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 import android.util.DisplayMetrics
 import android.view.WindowManager
 import androidx.test.filters.RequiresDevice
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
-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.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt
index 85a534c..62fa7b4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DragToDismissBubbleScreenTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.wm.shell.flicker.bubble
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLockreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
similarity index 92%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLockreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
index 0b1382b..416315e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLockreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
@@ -18,14 +18,14 @@
 
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Postsubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 import android.view.WindowInsets
 import android.view.WindowManager
 import androidx.test.filters.RequiresDevice
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.navBarLayerIsVisibleAtEnd
 import com.android.server.wm.flicker.navBarLayerPositionAtEnd
 import org.junit.Assume
@@ -36,7 +36,7 @@
 /**
  * Test launching a new activity from bubble.
  *
- * To run this test: `atest WMShellFlickerTests:LaunchBubbleFromLockScreen`
+ * To run this test: `atest WMShellFlickerTests:OpenActivityFromBubbleOnLocksreenTest`
  *
  * Actions:
  * ```
@@ -46,7 +46,7 @@
 @RequiresDevice
 @RunWith(Parameterized::class)
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-class OpenActivityFromBubbleOnLockreenTest(flicker: FlickerTest) : BaseBubbleScreen(flicker) {
+class OpenActivityFromBubbleOnLocksreenTest(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/OpenActivityFromBubbleTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt
index 50507bf..07ba4133 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTest.kt
@@ -17,12 +17,12 @@
 package com.android.wm.shell.flicker.bubble
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
-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.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt
index 94147e8..6c61710 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.wm.shell.flicker.bubble
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt
index 4be4dcd..29f76d0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTest.kt
@@ -17,12 +17,12 @@
 package com.android.wm.shell.flicker.bubble
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
-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.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt
index 7efbcdb..e323ebf 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/SendBubbleNotificationTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.wm.shell.flicker.bubble
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
 
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 88cf15e..1045a5a 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
@@ -18,10 +18,10 @@
 
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -44,7 +44,7 @@
  * ```
  *     1. All assertions are inherited from [EnterPipTest]
  *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
index 88542d5..2d2588e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
@@ -17,11 +17,11 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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 com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -43,7 +43,7 @@
  *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
  *        are inherited [PipTransition]
  *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt
index fb1eb01..02f6010 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTestCfArm.kt
@@ -16,10 +16,10 @@
 
 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 android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -40,7 +40,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
index 080e033..6c5a344 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
@@ -17,13 +17,13 @@
 package com.android.wm.shell.flicker.pip
 
 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 android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.LAUNCHER
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import com.android.server.wm.flicker.helpers.setRotation
-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
 
@@ -32,7 +32,7 @@
     override val transition: FlickerBuilder.() -> Unit
         get() = buildTransition {
             setup { this.setRotation(flicker.scenario.startRotation) }
-            teardown { this.setRotation(PlatformConsts.Rotation.ROTATION_0) }
+            teardown { this.setRotation(Rotation.ROTATION_0) }
         }
 
     /**
@@ -91,7 +91,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
index f27fa4a..e540ad5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTest.kt
@@ -17,10 +17,10 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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.Test
 import org.junit.runner.RunWith
@@ -43,7 +43,7 @@
  *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
  *        are inherited [PipTransition]
  *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt
index fbada69..05262fe 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipWithDismissButtonTestCfArm.kt
@@ -16,10 +16,10 @@
 
 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 android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -41,7 +41,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
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 47537c6..11bb0cc 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
@@ -17,10 +17,10 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -39,14 +39,6 @@
  *     Select "Via code behind" radio button
  *     Press Home button or swipe up to go Home and put [pipApp] in pip mode
  * ```
- * Notes:
- * ```
- *     1. All assertions are inherited from [EnterPipTest]
- *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
- *        including configuring navigation mode, initial orientation and ensuring no
- *        apps are running before setup
- * ```
  */
 @RequiresDevice
 @RunWith(Parameterized::class)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt
index e478050..90f99c0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.wm.shell.flicker.pip
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
index db50489..e079d547 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
@@ -20,18 +20,18 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
 import 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.entireScreenCovered
 import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
-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.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
 import org.junit.Assume
@@ -58,7 +58,7 @@
  *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
  *        are inherited [PipTransition]
  *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
@@ -69,8 +69,8 @@
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 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)
+    private val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90)
+    private val endingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0)
 
     /** Defines the transition used to run the test */
     override val transition: FlickerBuilder.() -> Unit
@@ -213,7 +213,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt
index ec5f13c..5841666 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationCfArm.kt
@@ -16,10 +16,10 @@
 
 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 android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -42,7 +42,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
index 3ef66d7..3272254 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
@@ -17,11 +17,11 @@
 package com.android.wm.shell.flicker.pip
 
 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.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.Test
 import org.junit.runners.Parameterized
 
@@ -130,7 +130,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
index c3c705e..1f060e9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTest.kt
@@ -16,10 +16,10 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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
@@ -40,7 +40,7 @@
  *     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],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt
index b487ff4..4390f0b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipViaAppUiButtonTestCfArm.kt
@@ -16,10 +16,10 @@
 
 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 android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -40,7 +40,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
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 f88f8d6..2001f48 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
@@ -17,11 +17,11 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.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
 
@@ -137,7 +137,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
index d2fbb2a2..313631c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTest.kt
@@ -18,11 +18,11 @@
 
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -47,7 +47,7 @@
  *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
  *        are inherited [PipTransition]
  *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt
index 8b3755e..eccb85d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaExpandButtonTestCfArm.kt
@@ -16,10 +16,10 @@
 
 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 android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -41,7 +41,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
index a9eb18d..93ffdd8d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt
@@ -18,11 +18,11 @@
 
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -46,7 +46,7 @@
  *     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],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt
index 39b1c82..6ab6a1f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTestCfArm.kt
@@ -16,10 +16,10 @@
 
 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 android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -40,7 +40,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(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 d577b4f..7d5f740 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
@@ -17,13 +17,13 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.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
@@ -45,7 +45,7 @@
  *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
  *        are inherited [PipTransition]
  *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
@@ -147,7 +147,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt
index 08db8ae..c096234 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTestTestCfArm.kt
@@ -16,10 +16,10 @@
 
 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 android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -41,7 +41,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
index fcb8af4..0b73aac 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTest.kt
@@ -17,12 +17,12 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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
@@ -61,7 +61,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt
index 30050bf..e064bf2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnPinchOpenTestCfArm.kt
@@ -16,10 +16,10 @@
 
 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 android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -40,7 +40,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
index 39ac49f..9c00744 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownOnShelfHeightChange.kt
@@ -17,10 +17,10 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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 com.android.wm.shell.flicker.Direction
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -45,7 +45,7 @@
  *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
  *        are inherited [PipTransition]
  *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
index 7db80a8..c23838a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
@@ -17,17 +17,17 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
 import 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.ImeAppHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
-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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume.assumeFalse
 import org.junit.Before
 import org.junit.FixMethodOrder
@@ -91,7 +91,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt
index be3bd60..d3d77d2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestCfArm.kt
@@ -16,10 +16,10 @@
 
 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 android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -37,7 +37,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt
index ef9920c..6f81116 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTestShellTransit.kt
@@ -17,10 +17,10 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.Assume
 import org.junit.Before
 import org.junit.FixMethodOrder
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 77a8c3c..109354a 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
@@ -17,11 +17,11 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
+import android.tools.common.Rotation
+import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.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
@@ -118,7 +118,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
index 511a651..c8d5624 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpOnShelfHeightChangeTest.kt
@@ -17,10 +17,10 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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 com.android.wm.shell.flicker.Direction
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -45,7 +45,7 @@
  *     1. Some default assertions (e.g., nav bar, status bar and screen covered)
  *        are inherited [PipTransition]
  *     2. Part of the test setup occurs automatically via
- *        [com.android.server.wm.flicker.TransitionRunnerWithRules],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
index e133443..85b2fbc 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipPinchInTest.kt
@@ -17,12 +17,12 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Postsubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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
@@ -61,7 +61,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(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 166416a..b30f308 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
@@ -19,15 +19,15 @@
 import android.app.Instrumentation
 import android.content.Intent
 import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
+import android.tools.device.helpers.WindowUtils
 import com.android.server.wm.flicker.helpers.PipAppHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
 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.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
 import org.junit.Test
@@ -70,7 +70,7 @@
     ): FlickerBuilder.() -> Unit {
         return {
             setup {
-                setRotation(PlatformConsts.Rotation.ROTATION_0)
+                setRotation(Rotation.ROTATION_0)
                 removeAllTasksButHome()
                 pipApp.launchViaIntentAndWaitForPip(wmHelper, stringExtras = stringExtras)
             }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
index 3f5d067..3850c1f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt
@@ -20,15 +20,15 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
 import 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.WindowUtils
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.testapp.ActivityOptions
 import com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION
-import com.android.server.wm.traces.common.service.PlatformConsts
 import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
 import org.junit.Assume
 import org.junit.Before
@@ -47,8 +47,8 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 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)
+    private val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0)
+    private val endingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90)
 
     /** {@inheritDoc} */
     override val transition: FlickerBuilder.() -> Unit
@@ -66,7 +66,7 @@
                 wmHelper
                     .StateSyncBuilder()
                     .withPipShown()
-                    .withRotation(PlatformConsts.Rotation.ROTATION_0)
+                    .withRotation(Rotation.ROTATION_0)
                     .withNavOrTaskBarVisible()
                     .withStatusBarVisible()
                     .waitForAndVerify()
@@ -79,7 +79,7 @@
                 wmHelper
                     .StateSyncBuilder()
                     .withFullScreenApp(pipApp)
-                    .withRotation(PlatformConsts.Rotation.ROTATION_90)
+                    .withRotation(Rotation.ROTATION_90)
                     .withNavOrTaskBarVisible()
                     .withStatusBarVisible()
                     .waitForAndVerify()
@@ -98,7 +98,7 @@
     @Presubmit
     @Test
     fun displayEndsAt90Degrees() {
-        flicker.assertWmEnd { hasRotation(PlatformConsts.Rotation.ROTATION_90) }
+        flicker.assertWmEnd { hasRotation(Rotation.ROTATION_90) }
     }
 
     @Presubmit
@@ -151,7 +151,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
index 720fe72..2cf8f61 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplay.kt
@@ -17,14 +17,14 @@
 package com.android.wm.shell.flicker.pip
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
 import 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.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -48,7 +48,7 @@
  *     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],
+ *        [android.tools.device.flicker.legacy.runner.TransitionRunner],
  *        including configuring navigation mode, initial orientation and ensuring no
  *        apps are running before setup
  * ```
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt
index daf3e1b..b7a2c47 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ShowPipAndRotateDisplayCfArm.kt
@@ -16,9 +16,9 @@
 
 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 android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt
index 36909dd..000ae8f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt
@@ -17,12 +17,12 @@
 package com.android.wm.shell.flicker.pip.tv
 
 import android.app.Instrumentation
+import android.tools.device.traces.parsers.WindowManagerStateHelper
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.BySelector
 import androidx.test.uiautomator.UiObject2
 import androidx.test.uiautomator.Until
 import com.android.server.wm.flicker.helpers.PipAppHelper
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
 /** Helper class for PIP app on AndroidTV */
 open class PipAppHelperTv(instrumentation: Instrumentation) : PipAppHelper(instrumentation) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
index dc1fe47..6104b7b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
@@ -20,10 +20,10 @@
 import android.app.IActivityManager
 import android.app.IProcessObserver
 import android.os.SystemClock
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
+import android.tools.device.traces.parsers.WindowManagerStateHelper
 import android.view.Surface.ROTATION_0
 import android.view.Surface.rotationToString
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
 import org.junit.After
 import org.junit.Assert.assertFalse
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 247403a..0c9c161 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
@@ -19,13 +19,13 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.datatypes.component.EdgeExtensionComponentMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.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
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt
index d3c6820..1b55f39 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt
@@ -20,12 +20,12 @@
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
 import 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.WindowUtils
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.wm.shell.flicker.appWindowBecomesInvisible
 import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
 import com.android.wm.shell.flicker.layerBecomesInvisible
@@ -104,14 +104,12 @@
     @Test
     fun secondaryAppBoundsIsFullscreenAtEnd() {
         flicker.assertLayers {
-            this.isVisible(secondaryApp)
-                .then()
-                .isInvisible(secondaryApp)
-                .then()
-                .invoke("secondaryAppBoundsIsFullscreenAtEnd") {
-                    val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
-                    it.visibleRegion(secondaryApp).coversExactly(displayBounds)
-                }
+            this.isVisible(secondaryApp).then().isInvisible(secondaryApp).then().invoke(
+                "secondaryAppBoundsIsFullscreenAtEnd"
+            ) {
+                val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
+                it.visibleRegion(secondaryApp).coversExactly(displayBounds)
+            }
         }
     }
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
index b44b681..bd2ffc1 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
@@ -19,11 +19,11 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.wm.shell.flicker.appWindowBecomesInvisible
 import com.android.wm.shell.flicker.layerBecomesInvisible
 import com.android.wm.shell.flicker.splitAppLayerBoundsBecomesInvisible
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
index 514365f..7db5ecc 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
@@ -19,12 +19,12 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
 import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
 import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt
index 4e36c36..ffdb87f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromAllApps.kt
@@ -19,13 +19,13 @@
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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 com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
 import com.android.wm.shell.flicker.appWindowBecomesVisible
 import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
@@ -186,7 +186,7 @@
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
                 // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt
index 5d37e85..792e2b0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromNotification.kt
@@ -19,13 +19,13 @@
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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 com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
 import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
 import com.android.wm.shell.flicker.layerBecomesVisible
@@ -208,7 +208,7 @@
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
                 // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt
index d086f7e..c1977e9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromShortcut.kt
@@ -19,12 +19,12 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.appWindowIsVisibleAtEnd
 import com.android.wm.shell.flicker.layerBecomesVisible
 import com.android.wm.shell.flicker.layerIsVisibleAtEnd
@@ -136,7 +136,7 @@
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
                 // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt
index 795a2c4..da80c6f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenByDragFromTaskbar.kt
@@ -19,13 +19,13 @@
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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 com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
 import com.android.wm.shell.flicker.appWindowBecomesVisible
 import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
@@ -205,7 +205,7 @@
         @JvmStatic
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
index a9cbb74..c453877 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
@@ -19,11 +19,11 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.wm.shell.flicker.appWindowBecomesVisible
 import com.android.wm.shell.flicker.layerBecomesVisible
 import com.android.wm.shell.flicker.layerIsVisibleAtEnd
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenBase.kt
index 8c0a303..7abdc06 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenBase.kt
@@ -17,8 +17,8 @@
 package com.android.wm.shell.flicker.splitscreen
 
 import android.content.Context
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.wm.shell.flicker.BaseTest
 
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 4f8cfca..7901f75 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
@@ -19,6 +19,12 @@
 import android.app.Instrumentation
 import android.graphics.Point
 import android.os.SystemClock
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.common.datatypes.component.IComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import android.view.InputDevice
 import android.view.MotionEvent
 import android.view.ViewConfiguration
@@ -32,16 +38,9 @@
 import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
 import com.android.server.wm.flicker.helpers.NotificationAppHelper
 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.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
 import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
-import java.util.Collections
 import org.junit.Assert.assertNotNull
 
 internal object SplitScreenUtils {
@@ -129,18 +128,12 @@
 
             // Find the second task in the upper right corner in split select mode by sorting
             // 'left' in descending order and 'top' in ascending order.
-            Collections.sort(
-                snapshots,
-                { t1: UiObject2, t2: UiObject2 ->
-                    t2.getVisibleBounds().left - t1.getVisibleBounds().left
-                }
-            )
-            Collections.sort(
-                snapshots,
-                { t1: UiObject2, t2: UiObject2 ->
-                    t1.getVisibleBounds().top - t2.getVisibleBounds().top
-                }
-            )
+            snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
+                t2.getVisibleBounds().left - t1.getVisibleBounds().left
+            }
+            snapshots.sortWith { t1: UiObject2, t2: UiObject2 ->
+                t1.getVisibleBounds().top - t2.getVisibleBounds().top
+            }
             snapshots[0].click()
         } else {
             tapl.workspace
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
index c7b81d9..fbb7c71 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
@@ -19,14 +19,15 @@
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
+import android.tools.device.traces.parsers.WindowManagerStateHelper
 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.WindowUtils
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.traces.common.service.PlatformConsts
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
 import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
 import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
@@ -133,7 +134,7 @@
             .waitForAndVerify()
     }
 
-    private fun isLandscape(rotation: PlatformConsts.Rotation): Boolean {
+    private fun isLandscape(rotation: Rotation): Boolean {
         val displayBounds = WindowUtils.getDisplayBounds(rotation)
         return displayBounds.width > displayBounds.height
     }
@@ -205,7 +206,7 @@
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
                 // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
index 940e0e9..d675bfb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
@@ -19,12 +19,12 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.appWindowBecomesVisible
 import com.android.wm.shell.flicker.layerBecomesVisible
 import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
@@ -166,7 +166,7 @@
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
                 // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
index 8c3bea8..2855c71 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
@@ -19,13 +19,13 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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 com.android.wm.shell.flicker.appWindowBecomesVisible
 import com.android.wm.shell.flicker.layerBecomesVisible
 import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
@@ -179,7 +179,7 @@
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
                 // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
index 06a1449..c29a917 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
@@ -19,13 +19,13 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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 com.android.wm.shell.flicker.appWindowBecomesVisible
 import com.android.wm.shell.flicker.layerBecomesVisible
 import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
@@ -179,7 +179,7 @@
         fun getParams(): List<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
                 // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt
index 193ab98..4c96b3a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBetweenSplitPairs.kt
@@ -19,11 +19,11 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
 import com.android.wm.shell.flicker.appWindowBecomesInvisible
 import com.android.wm.shell.flicker.appWindowBecomesVisible
diff --git a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
index fac0461..47a116b 100644
--- a/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/unittest/AndroidManifest.xml
@@ -20,6 +20,7 @@
     package="com.android.wm.shell.tests">
 
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+    <uses-permission android:name="android.permission.VIBRATE"/>
 
     <application android:debuggable="true" android:largeHeap="true">
         <uses-library android:name="android.test.mock" />
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
index e8784d7..bc0d93a 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/compatui/CompatUIControllerTest.java
@@ -475,6 +475,36 @@
         verify(mMockRestartDialogLayout).updateVisibility(true);
     }
 
+    @Test
+    public void testRestartLayoutRecreatedIfNeeded() {
+        final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
+                /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+        doReturn(true).when(mMockRestartDialogLayout)
+                .needsToBeRecreated(any(TaskInfo.class),
+                        any(ShellTaskOrganizer.TaskListener.class));
+
+        mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+        mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+
+        verify(mMockRestartDialogLayout, times(2))
+                .createLayout(anyBoolean());
+    }
+
+    @Test
+    public void testRestartLayoutNotRecreatedIfNotNeeded() {
+        final TaskInfo taskInfo = createTaskInfo(DISPLAY_ID, TASK_ID,
+                /* hasSizeCompat= */ true, CAMERA_COMPAT_CONTROL_HIDDEN);
+        doReturn(false).when(mMockRestartDialogLayout)
+                .needsToBeRecreated(any(TaskInfo.class),
+                        any(ShellTaskOrganizer.TaskListener.class));
+
+        mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+        mController.onCompatInfoChanged(taskInfo, mMockTaskListener);
+
+        verify(mMockRestartDialogLayout, times(1))
+                .createLayout(anyBoolean());
+    }
+
     private static TaskInfo createTaskInfo(int displayId, int taskId, boolean hasSizeCompat,
             @CameraCompatControlState int cameraCompatControlState) {
         RunningTaskInfo taskInfo = new RunningTaskInfo();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
index b6dbcf2..523cb66 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
@@ -48,7 +48,6 @@
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.splitscreen.SplitScreenController;
 import com.android.wm.shell.sysui.ShellController;
 import com.android.wm.shell.sysui.ShellInit;
 
@@ -82,7 +81,7 @@
     @Mock
     private ShellExecutor mMainExecutor;
     @Mock
-    private SplitScreenController mSplitScreenController;
+    private WindowManager mWindowManager;
 
     private DragAndDropController mController;
 
@@ -100,11 +99,6 @@
     }
 
     @Test
-    public void instantiateController_registerConfigChangeListener() {
-        verify(mShellController, times(1)).addConfigurationChangeListener(any());
-    }
-
-    @Test
     public void testIgnoreNonDefaultDisplays() {
         final int nonDefaultDisplayId = 12345;
         final View dragLayout = mock(View.class);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 0bb809d..2e2e49e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -134,6 +134,7 @@
         when(mSplitLayout.getBounds2()).thenReturn(mBounds2);
         when(mSplitLayout.getRootBounds()).thenReturn(mRootBounds);
         when(mSplitLayout.isLandscape()).thenReturn(false);
+        when(mSplitLayout.applyTaskChanges(any(), any(), any())).thenReturn(true);
 
         mRootTask = new TestRunningTaskInfoBuilder().build();
         mRootLeash = new SurfaceControl.Builder(mSurfaceSession).setName("test").build();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index bf62acf..11fda8b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -24,8 +24,8 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.wm.shell.startingsurface.SplashscreenContentDrawer.MAX_ANIMATION_DURATION;
-import static com.android.wm.shell.startingsurface.SplashscreenContentDrawer.MINIMAL_ANIMATION_DURATION;
+import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MAX_ANIMATION_DURATION;
+import static com.android.wm.shell.startingsurface.StartingSurfaceDrawer.MINIMAL_ANIMATION_DURATION;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
@@ -56,9 +56,11 @@
 import android.os.Looper;
 import android.os.UserHandle;
 import android.testing.TestableContext;
+import android.view.Display;
 import android.view.IWindowSession;
 import android.view.InsetsState;
 import android.view.Surface;
+import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.WindowMetrics;
@@ -104,7 +106,36 @@
     private ShellExecutor mTestExecutor;
     private final TestableContext mTestContext = new TestContext(
             InstrumentationRegistry.getInstrumentation().getTargetContext());
-    StartingSurfaceDrawer mStartingSurfaceDrawer;
+    TestStartingSurfaceDrawer mStartingSurfaceDrawer;
+
+    static final class TestStartingSurfaceDrawer extends StartingSurfaceDrawer{
+        int mAddWindowForTask = 0;
+
+        TestStartingSurfaceDrawer(Context context, ShellExecutor splashScreenExecutor,
+                IconProvider iconProvider, TransactionPool pool) {
+            super(context, splashScreenExecutor, iconProvider, pool);
+        }
+
+        @Override
+        protected boolean addWindow(int taskId, IBinder appToken, View view, Display display,
+                WindowManager.LayoutParams params, int suggestType) {
+            // listen for addView
+            mAddWindowForTask = taskId;
+            saveSplashScreenRecord(appToken, taskId, view, suggestType);
+            // Do not wait for background color
+            return false;
+        }
+
+        @Override
+        protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo,
+                boolean immediately) {
+            // listen for removeView
+            if (mAddWindowForTask == removalInfo.taskId) {
+                mAddWindowForTask = 0;
+            }
+            mStartingWindowRecords.remove(removalInfo.taskId);
+        }
+    }
 
     private static class TestContext extends TestableContext {
         TestContext(Context context) {
@@ -134,51 +165,44 @@
         doReturn(metrics).when(mMockWindowManager).getMaximumWindowMetrics();
         doNothing().when(mMockWindowManager).addView(any(), any());
         mTestExecutor = new HandlerExecutor(mTestHandler);
-        mStartingSurfaceDrawer = new StartingSurfaceDrawer(mTestContext, mTestExecutor,
-                mIconProvider, mTransactionPool);
         mStartingSurfaceDrawer = spy(
-                new StartingSurfaceDrawer(mTestContext, mTestExecutor, mIconProvider,
+                new TestStartingSurfaceDrawer(mTestContext, mTestExecutor, mIconProvider,
                         mTransactionPool));
-        spyOn(mStartingSurfaceDrawer.mSplashscreenWindowCreator);
-        spyOn(mStartingSurfaceDrawer.mWindowRecords);
-        spyOn(mStartingSurfaceDrawer.mWindowlessRecords);
     }
 
     @Test
     public void testAddSplashScreenSurface() {
         final int taskId = 1;
         final StartingWindowInfo windowInfo =
-                createWindowInfo(taskId, android.R.style.Theme, mBinder);
-        mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo,
+                createWindowInfo(taskId, android.R.style.Theme);
+        mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
                 STARTING_WINDOW_TYPE_SPLASH_SCREEN);
         waitHandlerIdle(mTestHandler);
-        verify(mStartingSurfaceDrawer.mSplashscreenWindowCreator).addWindow(
-                eq(taskId), eq(mBinder), any(), any(), any(),
+        verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
                 eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
+        assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
 
         StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo();
         removalInfo.taskId = windowInfo.taskInfo.taskId;
         mStartingSurfaceDrawer.removeStartingWindow(removalInfo);
         waitHandlerIdle(mTestHandler);
-        verify(mStartingSurfaceDrawer.mWindowRecords).removeWindow(any(), eq(false));
-        assertEquals(mStartingSurfaceDrawer.mWindowRecords.recordSize(), 0);
+        verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(false));
+        assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, 0);
     }
 
     @Test
     public void testFallbackDefaultTheme() {
         final int taskId = 1;
         final StartingWindowInfo windowInfo =
-                createWindowInfo(taskId, 0, mBinder);
+                createWindowInfo(taskId, 0);
         final int[] theme = new int[1];
         doAnswer(invocation -> theme[0] = (Integer) invocation.callRealMethod())
-                .when(mStartingSurfaceDrawer.mSplashscreenWindowCreator)
-                .getSplashScreenTheme(eq(0), any());
+                .when(mStartingSurfaceDrawer).getSplashScreenTheme(eq(0), any());
 
-        mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo,
+        mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
                 STARTING_WINDOW_TYPE_SPLASH_SCREEN);
         waitHandlerIdle(mTestHandler);
-        verify(mStartingSurfaceDrawer.mSplashscreenWindowCreator)
-                .getSplashScreenTheme(eq(0), any());
+        verify(mStartingSurfaceDrawer).getSplashScreenTheme(eq(0), any());
         assertNotEquals(theme[0], 0);
     }
 
@@ -217,7 +241,7 @@
     public void testRemoveTaskSnapshotWithImeSurfaceWhenOnImeDrawn() throws Exception {
         final int taskId = 1;
         final StartingWindowInfo windowInfo =
-                createWindowInfo(taskId, android.R.style.Theme, mBinder);
+                createWindowInfo(taskId, android.R.style.Theme);
         TaskSnapshot snapshot = createTaskSnapshot(100, 100, new Point(100, 100),
                 new Rect(0, 0, 0, 50), true /* hasImeSurface */);
         final IWindowSession session = WindowManagerGlobal.getWindowSession();
@@ -246,7 +270,7 @@
             when(TaskSnapshotWindow.create(eq(windowInfo), eq(mBinder), eq(snapshot), any(),
                     any())).thenReturn(mockSnapshotWindow);
             // Simulate a task snapshot window created with IME snapshot shown.
-            mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, snapshot);
+            mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, mBinder, snapshot);
             waitHandlerIdle(mTestHandler);
 
             // Verify the task snapshot with IME snapshot will be removed when received the real IME
@@ -254,36 +278,27 @@
             // makeTaskSnapshotWindow shall call removeWindowSynced before there add a new
             // StartingWindowRecord for the task.
             mStartingSurfaceDrawer.onImeDrawnOnTask(1);
-            verify(mStartingSurfaceDrawer.mWindowRecords, times(2))
-                    .removeWindow(any(), eq(true));
+            verify(mStartingSurfaceDrawer, times(2))
+                    .removeWindowSynced(any(), eq(true));
         }
     }
 
     @Test
     public void testClearAllWindows() {
         final int taskId = 1;
-        mStartingSurfaceDrawer.mWindowRecords.addRecord(taskId,
-                new StartingSurfaceDrawer.StartingWindowRecord() {
-                    @Override
-                    public void removeIfPossible(StartingWindowRemovalInfo info,
-                            boolean immediately) {
+        final StartingWindowInfo windowInfo =
+                createWindowInfo(taskId, android.R.style.Theme);
+        mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
+                STARTING_WINDOW_TYPE_SPLASH_SCREEN);
+        waitHandlerIdle(mTestHandler);
+        verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
+                eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
+        assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
 
-                    }
-                });
-        mStartingSurfaceDrawer.mWindowlessRecords.addRecord(taskId,
-                new StartingSurfaceDrawer.StartingWindowRecord() {
-                    @Override
-                    public void removeIfPossible(StartingWindowRemovalInfo info,
-                            boolean immediately) {
-
-                    }
-                });
         mStartingSurfaceDrawer.clearAllWindows();
         waitHandlerIdle(mTestHandler);
-        verify(mStartingSurfaceDrawer.mWindowRecords).removeWindow(any(), eq(true));
-        assertEquals(mStartingSurfaceDrawer.mWindowRecords.recordSize(), 0);
-        verify(mStartingSurfaceDrawer.mWindowlessRecords).removeWindow(any(), eq(true));
-        assertEquals(mStartingSurfaceDrawer.mWindowlessRecords.recordSize(), 0);
+        verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(true));
+        assertEquals(mStartingSurfaceDrawer.mStartingWindowRecords.size(), 0);
     }
 
     @Test
@@ -336,7 +351,7 @@
                 longAppDuration, longAppDuration));
     }
 
-    private StartingWindowInfo createWindowInfo(int taskId, int themeResId, IBinder appToken) {
+    private StartingWindowInfo createWindowInfo(int taskId, int themeResId) {
         StartingWindowInfo windowInfo = new StartingWindowInfo();
         final ActivityInfo info = new ActivityInfo();
         info.applicationInfo = new ApplicationInfo();
@@ -345,7 +360,6 @@
         final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
         taskInfo.topActivityInfo = info;
         taskInfo.taskId = taskId;
-        windowInfo.appToken = appToken;
         windowInfo.targetActivityInfo = info;
         windowInfo.taskInfo = taskInfo;
         windowInfo.topOpaqueWindowInsetsState = new InsetsState();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
index 3550721..1d1aa79 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.java
@@ -49,6 +49,7 @@
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.desktopmode.DesktopModeController;
 import com.android.wm.shell.desktopmode.DesktopTasksController;
+import com.android.wm.shell.splitscreen.SplitScreenController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -73,6 +74,7 @@
     @Mock private Choreographer mMainChoreographer;
     @Mock private ShellTaskOrganizer mTaskOrganizer;
     @Mock private DisplayController mDisplayController;
+    @Mock private SplitScreenController mSplitScreenController;
     @Mock private SyncTransactionQueue mSyncQueue;
     @Mock private DesktopModeController mDesktopModeController;
     @Mock private DesktopTasksController mDesktopTasksController;
@@ -98,6 +100,7 @@
                 mSyncQueue,
                 Optional.of(mDesktopModeController),
                 Optional.of(mDesktopTasksController),
+                Optional.of(mSplitScreenController),
                 mDesktopModeWindowDecorFactory,
                 mMockInputMonitorFactory
             );
diff --git a/libs/dream/OWNERS b/libs/dream/OWNERS
new file mode 100644
index 0000000..a4b0127
--- /dev/null
+++ b/libs/dream/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/dreams/OWNERS
\ No newline at end of file
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index bcbe706..536bb49 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -332,6 +332,7 @@
         "jni/android_graphics_Matrix.cpp",
         "jni/android_graphics_Picture.cpp",
         "jni/android_graphics_DisplayListCanvas.cpp",
+        "jni/android_graphics_Mesh.cpp",
         "jni/android_graphics_RenderNode.cpp",
         "jni/android_nio_utils.cpp",
         "jni/android_util_PathParser.cpp",
@@ -351,7 +352,6 @@
         "jni/ImageDecoder.cpp",
         "jni/Interpolator.cpp",
         "jni/MeshSpecification.cpp",
-        "jni/Mesh.cpp",
         "jni/MaskFilter.cpp",
         "jni/NinePatch.cpp",
         "jni/NinePatchPeeker.cpp",
@@ -538,6 +538,7 @@
         "Interpolator.cpp",
         "LightingInfo.cpp",
         "Matrix.cpp",
+        "Mesh.cpp",
         "MemoryPolicy.cpp",
         "PathParser.cpp",
         "Properties.cpp",
diff --git a/libs/hwui/DisplayListOps.in b/libs/hwui/DisplayListOps.in
index e2127ef..a18ba1c 100644
--- a/libs/hwui/DisplayListOps.in
+++ b/libs/hwui/DisplayListOps.in
@@ -52,4 +52,5 @@
 X(DrawVectorDrawable)
 X(DrawRippleDrawable)
 X(DrawWebView)
-X(DrawMesh)
+X(DrawSkMesh)
+X(DrawMesh)
\ No newline at end of file
diff --git a/libs/hwui/MemoryPolicy.h b/libs/hwui/MemoryPolicy.h
index 2f0f7f5..41ced8c 100644
--- a/libs/hwui/MemoryPolicy.h
+++ b/libs/hwui/MemoryPolicy.h
@@ -53,8 +53,8 @@
     // Whether or not to only purge scratch resources when triggering UI Hidden or background
     // collection
     bool purgeScratchOnly = true;
-    // Whether or not to trigger releasing GPU context when all contexts are stopped
-    bool releaseContextOnStoppedOnly = true;
+    // EXPERIMENTAL: Whether or not to trigger releasing GPU context when all contexts are stopped
+    bool releaseContextOnStoppedOnly = false;
 };
 
 const MemoryPolicy& loadMemoryPolicy();
diff --git a/libs/hwui/Mesh.cpp b/libs/hwui/Mesh.cpp
new file mode 100644
index 0000000..e59bc95
--- /dev/null
+++ b/libs/hwui/Mesh.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+#include "Mesh.h"
+
+#include <GLES/gl.h>
+#include <SkMesh.h>
+
+#include "SafeMath.h"
+
+static size_t min_vcount_for_mode(SkMesh::Mode mode) {
+    switch (mode) {
+        case SkMesh::Mode::kTriangles:
+            return 3;
+        case SkMesh::Mode::kTriangleStrip:
+            return 3;
+    }
+}
+
+// Re-implementation of SkMesh::validate to validate user side that their mesh is valid.
+std::tuple<bool, SkString> Mesh::validate() {
+#define FAIL_MESH_VALIDATE(...) return std::make_tuple(false, SkStringPrintf(__VA_ARGS__))
+    if (!mMeshSpec) {
+        FAIL_MESH_VALIDATE("MeshSpecification is required.");
+    }
+    if (mVertexBufferData.empty()) {
+        FAIL_MESH_VALIDATE("VertexBuffer is required.");
+    }
+
+    auto meshStride = mMeshSpec->stride();
+    auto meshMode = SkMesh::Mode(mMode);
+    SafeMath sm;
+    size_t vsize = sm.mul(meshStride, mVertexCount);
+    if (sm.add(vsize, mVertexOffset) > mVertexBufferData.size()) {
+        FAIL_MESH_VALIDATE(
+                "The vertex buffer offset and vertex count reads beyond the end of the"
+                " vertex buffer.");
+    }
+
+    if (mVertexOffset % meshStride != 0) {
+        FAIL_MESH_VALIDATE("The vertex offset (%zu) must be a multiple of the vertex stride (%zu).",
+                           mVertexOffset, meshStride);
+    }
+
+    if (size_t uniformSize = mMeshSpec->uniformSize()) {
+        if (!mBuilder->fUniforms || mBuilder->fUniforms->size() < uniformSize) {
+            FAIL_MESH_VALIDATE("The uniform data is %zu bytes but must be at least %zu.",
+                               mBuilder->fUniforms->size(), uniformSize);
+        }
+    }
+
+    auto modeToStr = [](SkMesh::Mode m) {
+        switch (m) {
+            case SkMesh::Mode::kTriangles:
+                return "triangles";
+            case SkMesh::Mode::kTriangleStrip:
+                return "triangle-strip";
+        }
+    };
+    if (!mIndexBufferData.empty()) {
+        if (mIndexCount < min_vcount_for_mode(meshMode)) {
+            FAIL_MESH_VALIDATE("%s mode requires at least %zu indices but index count is %zu.",
+                               modeToStr(meshMode), min_vcount_for_mode(meshMode), mIndexCount);
+        }
+        size_t isize = sm.mul(sizeof(uint16_t), mIndexCount);
+        if (sm.add(isize, mIndexOffset) > mIndexBufferData.size()) {
+            FAIL_MESH_VALIDATE(
+                    "The index buffer offset and index count reads beyond the end of the"
+                    " index buffer.");
+        }
+        // If we allow 32 bit indices then this should enforce 4 byte alignment in that case.
+        if (!SkIsAlign2(mIndexOffset)) {
+            FAIL_MESH_VALIDATE("The index offset must be a multiple of 2.");
+        }
+    } else {
+        if (mVertexCount < min_vcount_for_mode(meshMode)) {
+            FAIL_MESH_VALIDATE("%s mode requires at least %zu vertices but vertex count is %zu.",
+                               modeToStr(meshMode), min_vcount_for_mode(meshMode), mVertexCount);
+        }
+        SkASSERT(!fICount);
+        SkASSERT(!fIOffset);
+    }
+
+    if (!sm.ok()) {
+        FAIL_MESH_VALIDATE("Overflow");
+    }
+#undef FAIL_MESH_VALIDATE
+    return {true, {}};
+}
diff --git a/libs/hwui/Mesh.h b/libs/hwui/Mesh.h
new file mode 100644
index 0000000..9836817
--- /dev/null
+++ b/libs/hwui/Mesh.h
@@ -0,0 +1,208 @@
+/*
+ * 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.
+ */
+
+#ifndef MESH_H_
+#define MESH_H_
+
+#include <GrDirectContext.h>
+#include <SkMesh.h>
+#include <jni.h>
+#include <log/log.h>
+
+#include <utility>
+
+class MeshUniformBuilder {
+public:
+    struct MeshUniform {
+        template <typename T>
+        std::enable_if_t<std::is_trivially_copyable<T>::value, MeshUniform> operator=(
+                const T& val) {
+            if (!fVar) {
+                LOG_FATAL("Assigning to missing variable");
+            } else if (sizeof(val) != fVar->sizeInBytes()) {
+                LOG_FATAL("Incorrect value size");
+            } else {
+                void* dst = reinterpret_cast<void*>(
+                        reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+                memcpy(dst, &val, sizeof(val));
+            }
+        }
+
+        MeshUniform& operator=(const SkMatrix& val) {
+            if (!fVar) {
+                LOG_FATAL("Assigning to missing variable");
+            } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
+                LOG_FATAL("Incorrect value size");
+            } else {
+                float* data = reinterpret_cast<float*>(
+                        reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+                data[0] = val.get(0);
+                data[1] = val.get(3);
+                data[2] = val.get(6);
+                data[3] = val.get(1);
+                data[4] = val.get(4);
+                data[5] = val.get(7);
+                data[6] = val.get(2);
+                data[7] = val.get(5);
+                data[8] = val.get(8);
+            }
+            return *this;
+        }
+
+        template <typename T>
+        bool set(const T val[], const int count) {
+            static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
+            if (!fVar) {
+                LOG_FATAL("Assigning to missing variable");
+                return false;
+            } else if (sizeof(T) * count != fVar->sizeInBytes()) {
+                LOG_FATAL("Incorrect value size");
+                return false;
+            } else {
+                void* dst = reinterpret_cast<void*>(
+                        reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
+                memcpy(dst, val, sizeof(T) * count);
+            }
+            return true;
+        }
+
+        MeshUniformBuilder* fOwner;
+        const SkRuntimeEffect::Uniform* fVar;
+    };
+    MeshUniform uniform(std::string_view name) { return {this, fMeshSpec->findUniform(name)}; }
+
+    explicit MeshUniformBuilder(sk_sp<SkMeshSpecification> meshSpec) {
+        fMeshSpec = sk_sp(meshSpec);
+        fUniforms = (SkData::MakeZeroInitialized(meshSpec->uniformSize()));
+    }
+
+    sk_sp<SkData> fUniforms;
+
+private:
+    void* writableUniformData() {
+        if (!fUniforms->unique()) {
+            fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
+        }
+        return fUniforms->writable_data();
+    }
+
+    sk_sp<SkMeshSpecification> fMeshSpec;
+};
+
+class Mesh {
+public:
+    Mesh(const sk_sp<SkMeshSpecification>& meshSpec, int mode, const void* vertexBuffer,
+         size_t vertexBufferSize, jint vertexCount, jint vertexOffset,
+         std::unique_ptr<MeshUniformBuilder> builder, const SkRect& bounds)
+            : mMeshSpec(meshSpec)
+            , mMode(mode)
+            , mVertexCount(vertexCount)
+            , mVertexOffset(vertexOffset)
+            , mBuilder(std::move(builder))
+            , mBounds(bounds) {
+        copyToVector(mVertexBufferData, vertexBuffer, vertexBufferSize);
+    }
+
+    Mesh(const sk_sp<SkMeshSpecification>& meshSpec, int mode, const void* vertexBuffer,
+         size_t vertexBufferSize, jint vertexCount, jint vertexOffset, const void* indexBuffer,
+         size_t indexBufferSize, jint indexCount, jint indexOffset,
+         std::unique_ptr<MeshUniformBuilder> builder, const SkRect& bounds)
+            : mMeshSpec(meshSpec)
+            , mMode(mode)
+            , mVertexCount(vertexCount)
+            , mVertexOffset(vertexOffset)
+            , mIndexCount(indexCount)
+            , mIndexOffset(indexOffset)
+            , mBuilder(std::move(builder))
+            , mBounds(bounds) {
+        copyToVector(mVertexBufferData, vertexBuffer, vertexBufferSize);
+        copyToVector(mIndexBufferData, indexBuffer, indexBufferSize);
+    }
+
+    Mesh(Mesh&&) = default;
+
+    Mesh& operator=(Mesh&&) = default;
+
+    [[nodiscard]] std::tuple<bool, SkString> validate();
+
+    void updateSkMesh(GrDirectContext* context) const {
+        GrDirectContext::DirectContextID genId = GrDirectContext::DirectContextID();
+        if (context) {
+            genId = context->directContextID();
+        }
+
+        if (mIsDirty || genId != mGenerationId) {
+            auto vb = SkMesh::MakeVertexBuffer(
+                    context, reinterpret_cast<const void*>(mVertexBufferData.data()),
+                    mVertexBufferData.size());
+            auto meshMode = SkMesh::Mode(mMode);
+            if (!mIndexBufferData.empty()) {
+                auto ib = SkMesh::MakeIndexBuffer(
+                        context, reinterpret_cast<const void*>(mIndexBufferData.data()),
+                        mIndexBufferData.size());
+                mMesh = SkMesh::MakeIndexed(mMeshSpec, meshMode, vb, mVertexCount, mVertexOffset,
+                                            ib, mIndexCount, mIndexOffset, mBuilder->fUniforms,
+                                            mBounds)
+                                .mesh;
+            } else {
+                mMesh = SkMesh::Make(mMeshSpec, meshMode, vb, mVertexCount, mVertexOffset,
+                                     mBuilder->fUniforms, mBounds)
+                                .mesh;
+            }
+            mIsDirty = false;
+            mGenerationId = genId;
+        }
+    }
+
+    SkMesh& getSkMesh() const {
+        LOG_FATAL_IF(mIsDirty,
+                     "Attempt to obtain SkMesh when Mesh is dirty, did you "
+                     "forget to call updateSkMesh with a GrDirectContext? "
+                     "Defensively creating a CPU mesh");
+        return mMesh;
+    }
+
+    void markDirty() { mIsDirty = true; }
+
+    MeshUniformBuilder* uniformBuilder() { return mBuilder.get(); }
+
+private:
+    void copyToVector(std::vector<uint8_t>& dst, const void* src, size_t srcSize) {
+        if (src) {
+            dst.resize(srcSize);
+            memcpy(dst.data(), src, srcSize);
+        }
+    }
+
+    sk_sp<SkMeshSpecification> mMeshSpec;
+    int mMode = 0;
+
+    std::vector<uint8_t> mVertexBufferData;
+    size_t mVertexCount = 0;
+    size_t mVertexOffset = 0;
+
+    std::vector<uint8_t> mIndexBufferData;
+    size_t mIndexCount = 0;
+    size_t mIndexOffset = 0;
+
+    std::unique_ptr<MeshUniformBuilder> mBuilder;
+    SkRect mBounds{};
+
+    mutable SkMesh mMesh{};
+    mutable bool mIsDirty = true;
+    mutable GrDirectContext::DirectContextID mGenerationId = GrDirectContext::DirectContextID();
+};
+#endif  // MESH_H_
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 659aec0..0b58406 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -24,6 +24,7 @@
 #include <experimental/type_traits>
 #include <utility>
 
+#include "Mesh.h"
 #include "SkAndroidFrameworkUtils.h"
 #include "SkBlendMode.h"
 #include "SkCanvas.h"
@@ -502,14 +503,14 @@
         c->drawVertices(vertices, mode, paint);
     }
 };
-struct DrawMesh final : Op {
-    static const auto kType = Type::DrawMesh;
-    DrawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
+struct DrawSkMesh final : Op {
+    static const auto kType = Type::DrawSkMesh;
+    DrawSkMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
             : cpuMesh(mesh), blender(std::move(blender)), paint(paint) {
         isGpuBased = false;
     }
 
-    SkMesh cpuMesh;
+    const SkMesh& cpuMesh;
     mutable SkMesh gpuMesh;
     sk_sp<SkBlender> blender;
     SkPaint paint;
@@ -517,6 +518,7 @@
     mutable GrDirectContext::DirectContextID contextId;
     void draw(SkCanvas* c, const SkMatrix&) const {
         GrDirectContext* directContext = c->recordingContext()->asDirectContext();
+
         GrDirectContext::DirectContextID id = directContext->directContextID();
         if (!isGpuBased || contextId != id) {
             sk_sp<SkMesh::VertexBuffer> vb =
@@ -543,6 +545,18 @@
         c->drawMesh(gpuMesh, blender, paint);
     }
 };
+
+struct DrawMesh final : Op {
+    static const auto kType = Type::DrawMesh;
+    DrawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint)
+            : mesh(mesh), blender(std::move(blender)), paint(paint) {}
+
+    const Mesh& mesh;
+    sk_sp<SkBlender> blender;
+    SkPaint paint;
+
+    void draw(SkCanvas* c, const SkMatrix&) const { c->drawMesh(mesh.getSkMesh(), blender, paint); }
+};
 struct DrawAtlas final : Op {
     static const auto kType = Type::DrawAtlas;
     DrawAtlas(const SkImage* atlas, int count, SkBlendMode mode, const SkSamplingOptions& sampling,
@@ -859,6 +873,10 @@
 }
 void DisplayListData::drawMesh(const SkMesh& mesh, const sk_sp<SkBlender>& blender,
                                const SkPaint& paint) {
+    this->push<DrawSkMesh>(0, mesh, blender, paint);
+}
+void DisplayListData::drawMesh(const Mesh& mesh, const sk_sp<SkBlender>& blender,
+                               const SkPaint& paint) {
     this->push<DrawMesh>(0, mesh, blender, paint);
 }
 void DisplayListData::drawAtlas(const SkImage* atlas, const SkRSXform xforms[], const SkRect texs[],
@@ -1205,6 +1223,9 @@
                                  const SkPaint& paint) {
     fDL->drawMesh(mesh, blender, paint);
 }
+void RecordingCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint) {
+    fDL->drawMesh(mesh, blender, paint);
+}
 void RecordingCanvas::onDrawAtlas2(const SkImage* atlas, const SkRSXform xforms[],
                                    const SkRect texs[], const SkColor colors[], int count,
                                    SkBlendMode bmode, const SkSamplingOptions& sampling,
@@ -1223,5 +1244,14 @@
     fDL->drawWebView(drawable);
 }
 
+[[nodiscard]] const SkMesh& DrawMeshPayload::getSkMesh() const {
+    LOG_FATAL_IF(!meshWrapper && !mesh, "One of Mesh or Mesh must be non-null");
+    if (meshWrapper) {
+        return meshWrapper->getSkMesh();
+    } else {
+        return *mesh;
+    }
+}
+
 }  // namespace uirenderer
 }  // namespace android
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 8409e13..1f4ba5d 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -28,6 +28,7 @@
 #include <log/log.h>
 
 #include <cstdlib>
+#include <utility>
 #include <vector>
 
 #include "CanvasTransform.h"
@@ -40,6 +41,7 @@
 
 enum class SkBlendMode;
 class SkRRect;
+class Mesh;
 
 namespace android {
 namespace uirenderer {
@@ -66,6 +68,18 @@
 
 static_assert(sizeof(DisplayListOp) == 4);
 
+class DrawMeshPayload {
+public:
+    explicit DrawMeshPayload(const SkMesh* mesh) : mesh(mesh) {}
+    explicit DrawMeshPayload(const Mesh* meshWrapper) : meshWrapper(meshWrapper) {}
+
+    [[nodiscard]] const SkMesh& getSkMesh() const;
+
+private:
+    const SkMesh* mesh = nullptr;
+    const Mesh* meshWrapper = nullptr;
+};
+
 struct DrawImagePayload {
     explicit DrawImagePayload(Bitmap& bitmap)
             : image(bitmap.makeImage()), palette(bitmap.palette()) {
@@ -143,6 +157,7 @@
     void drawDRRect(const SkRRect&, const SkRRect&, const SkPaint&);
 
     void drawMesh(const SkMesh&, const sk_sp<SkBlender>&, const SkPaint&);
+    void drawMesh(const Mesh&, const sk_sp<SkBlender>&, const SkPaint&);
 
     void drawAnnotation(const SkRect&, const char*, SkData*);
     void drawDrawable(SkDrawable*, const SkMatrix*);
@@ -247,6 +262,7 @@
                      SkBlendMode, const SkSamplingOptions&, const SkRect*, const SkPaint*) override;
     void onDrawShadowRec(const SkPath&, const SkDrawShadowRec&) override;
 
+    void drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint);
     void drawVectorDrawable(VectorDrawableRoot* tree);
     void drawWebView(skiapipeline::FunctorDrawable*);
 
diff --git a/libs/hwui/SafeMath.h b/libs/hwui/SafeMath.h
new file mode 100644
index 0000000..4d6adf5
--- /dev/null
+++ b/libs/hwui/SafeMath.h
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+#ifndef SkSafeMath_DEFINED
+#define SkSafeMath_DEFINED
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+// Copy of Skia's SafeMath API used to validate Mesh parameters to support
+// deferred creation of SkMesh instances on RenderThread.
+// SafeMath always check that a series of operations do not overflow.
+// This must be correct for all platforms, because this is a check for safety at runtime.
+
+class SafeMath {
+public:
+    SafeMath() = default;
+
+    bool ok() const { return fOK; }
+    explicit operator bool() const { return fOK; }
+
+    size_t mul(size_t x, size_t y) {
+        return sizeof(size_t) == sizeof(uint64_t) ? mul64(x, y) : mul32(x, y);
+    }
+
+    size_t add(size_t x, size_t y) {
+        size_t result = x + y;
+        fOK &= result >= x;
+        return result;
+    }
+
+    /**
+     *  Return a + b, unless this result is an overflow/underflow. In those cases, fOK will
+     *  be set to false, and it is undefined what this returns.
+     */
+    int addInt(int a, int b) {
+        if (b < 0 && a < std::numeric_limits<int>::min() - b) {
+            fOK = false;
+            return a;
+        } else if (b > 0 && a > std::numeric_limits<int>::max() - b) {
+            fOK = false;
+            return a;
+        }
+        return a + b;
+    }
+
+    // These saturate to their results
+    static size_t Add(size_t x, size_t y) {
+        SafeMath tmp;
+        size_t sum = tmp.add(x, y);
+        return tmp.ok() ? sum : SIZE_MAX;
+    }
+
+    static size_t Mul(size_t x, size_t y) {
+        SafeMath tmp;
+        size_t prod = tmp.mul(x, y);
+        return tmp.ok() ? prod : SIZE_MAX;
+    }
+
+private:
+    uint32_t mul32(uint32_t x, uint32_t y) {
+        uint64_t bx = x;
+        uint64_t by = y;
+        uint64_t result = bx * by;
+        fOK &= result >> 32 == 0;
+        // Overflow information is capture in fOK. Return the result modulo 2^32.
+        return (uint32_t)result;
+    }
+
+    uint64_t mul64(uint64_t x, uint64_t y) {
+        if (x <= std::numeric_limits<uint64_t>::max() >> 32 &&
+            y <= std::numeric_limits<uint64_t>::max() >> 32) {
+            return x * y;
+        } else {
+            auto hi = [](uint64_t x) { return x >> 32; };
+            auto lo = [](uint64_t x) { return x & 0xFFFFFFFF; };
+
+            uint64_t lx_ly = lo(x) * lo(y);
+            uint64_t hx_ly = hi(x) * lo(y);
+            uint64_t lx_hy = lo(x) * hi(y);
+            uint64_t hx_hy = hi(x) * hi(y);
+            uint64_t result = 0;
+            result = this->add(lx_ly, (hx_ly << 32));
+            result = this->add(result, (lx_hy << 32));
+            fOK &= (hx_hy + (hx_ly >> 32) + (lx_hy >> 32)) == 0;
+
+            return result;
+        }
+    }
+    bool fOK = true;
+};
+
+#endif  // SkSafeMath_DEFINED
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index d0124f5..7a12769 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -39,21 +39,22 @@
 #include <SkShader.h>
 #include <SkTextBlob.h>
 #include <SkVertices.h>
+#include <log/log.h>
+#include <ui/FatVector.h>
 
 #include <memory>
 #include <optional>
 #include <utility>
 
 #include "CanvasProperty.h"
+#include "Mesh.h"
 #include "NinePatchUtils.h"
 #include "VectorDrawable.h"
 #include "hwui/Bitmap.h"
 #include "hwui/MinikinUtils.h"
 #include "hwui/PaintFilter.h"
-#include <log/log.h>
 #include "pipeline/skia/AnimatedDrawables.h"
 #include "pipeline/skia/HolePunch.h"
-#include <ui/FatVector.h>
 
 namespace android {
 
@@ -572,8 +573,14 @@
     applyLooper(&paint, [&](const SkPaint& p) { mCanvas->drawVertices(vertices, mode, p); });
 }
 
-void SkiaCanvas::drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender, const SkPaint& paint) {
-    mCanvas->drawMesh(mesh, blender, paint);
+void SkiaCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) {
+    GrDirectContext* context = nullptr;
+    auto recordingContext = mCanvas->recordingContext();
+    if (recordingContext) {
+        context = recordingContext->asDirectContext();
+    }
+    mesh.updateSkMesh(context);
+    mCanvas->drawMesh(mesh.getSkMesh(), blender, paint);
 }
 
 // ----------------------------------------------------------------------------
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index f2c286a..b785989 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -129,8 +129,7 @@
                          float sweepAngle, bool useCenter, const Paint& paint) override;
     virtual void drawPath(const SkPath& path, const Paint& paint) override;
     virtual void drawVertices(const SkVertices*, SkBlendMode, const Paint& paint) override;
-    virtual void drawMesh(const SkMesh& mesh, sk_sp<SkBlender> blender,
-                          const SkPaint& paint) override;
+    virtual void drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) override;
 
     virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) override;
     virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* paint) override;
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 2a20191..44ee31d 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -16,18 +16,17 @@
 
 #pragma once
 
-#include <cutils/compiler.h>
-#include <utils/Functor.h>
 #include <SaveFlags.h>
-
-#include <androidfw/ResourceTypes.h>
-#include "Properties.h"
-#include "pipeline/skia/AnimatedDrawables.h"
-#include "utils/Macros.h"
-
 #include <SkBitmap.h>
 #include <SkCanvas.h>
 #include <SkMatrix.h>
+#include <androidfw/ResourceTypes.h>
+#include <cutils/compiler.h>
+#include <utils/Functor.h>
+
+#include "Properties.h"
+#include "pipeline/skia/AnimatedDrawables.h"
+#include "utils/Macros.h"
 
 class SkAnimatedImage;
 enum class SkBlendMode;
@@ -35,6 +34,7 @@
 class SkRRect;
 class SkRuntimeShaderBuilder;
 class SkVertices;
+class Mesh;
 
 namespace minikin {
 class Font;
@@ -227,7 +227,7 @@
                          float sweepAngle, bool useCenter, const Paint& paint) = 0;
     virtual void drawPath(const SkPath& path, const Paint& paint) = 0;
     virtual void drawVertices(const SkVertices*, SkBlendMode, const Paint& paint) = 0;
-    virtual void drawMesh(const SkMesh& mesh, sk_sp<SkBlender>, const SkPaint& paint) = 0;
+    virtual void drawMesh(const Mesh& mesh, sk_sp<SkBlender>, const Paint& paint) = 0;
 
     // Bitmap-based
     virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) = 0;
diff --git a/libs/hwui/jni/GraphicsJNI.h b/libs/hwui/jni/GraphicsJNI.h
index 6b983c1..24f9e82 100644
--- a/libs/hwui/jni/GraphicsJNI.h
+++ b/libs/hwui/jni/GraphicsJNI.h
@@ -46,10 +46,16 @@
 
     static void setJavaVM(JavaVM* javaVM);
 
-    /** returns a pointer to the JavaVM provided when we initialized the module */
+    /**
+     * returns a pointer to the JavaVM provided when we initialized the module
+     * DEPRECATED: Objects should know the JavaVM that created them
+     */
     static JavaVM* getJavaVM() { return mJavaVM; }
 
-    /** return a pointer to the JNIEnv for this thread */
+    /**
+     * return a pointer to the JNIEnv for this thread
+     * DEPRECATED: Objects should know the JavaVM that created them
+     */
     static JNIEnv* getJNIEnv();
 
     /** create a JNIEnv* for this thread or assert if one already exists */
@@ -337,13 +343,21 @@
     JGlobalRefHolder(JavaVM* vm, jobject object) : mVm(vm), mObject(object) {}
 
     virtual ~JGlobalRefHolder() {
-        GraphicsJNI::getJNIEnv()->DeleteGlobalRef(mObject);
+        env()->DeleteGlobalRef(mObject);
         mObject = nullptr;
     }
 
     jobject object() { return mObject; }
     JavaVM* vm() { return mVm; }
 
+    JNIEnv* env() {
+        JNIEnv* env;
+        if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+            LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
+        }
+        return env;
+    }
+
 private:
     JGlobalRefHolder(const JGlobalRefHolder&) = delete;
     void operator=(const JGlobalRefHolder&) = delete;
diff --git a/libs/hwui/jni/Interpolator.cpp b/libs/hwui/jni/Interpolator.cpp
index fc3d70b..c71e308 100644
--- a/libs/hwui/jni/Interpolator.cpp
+++ b/libs/hwui/jni/Interpolator.cpp
@@ -24,12 +24,8 @@
 
     AutoJavaFloatArray autoValues(env, valueArray);
     AutoJavaFloatArray autoBlend(env, blendArray, 4);
-#ifdef SK_SCALAR_IS_FLOAT
     SkScalar* scalars = autoValues.ptr();
     SkScalar* blend = autoBlend.ptr();
-#else
-    #error Need to convert float array to SkScalar array before calling the following function.
-#endif
 
     interp->setKeyFrame(index, msec, scalars, blend);
 }
diff --git a/libs/hwui/jni/JvmErrorReporter.h b/libs/hwui/jni/JvmErrorReporter.h
index 5e10b9d..3a35875 100644
--- a/libs/hwui/jni/JvmErrorReporter.h
+++ b/libs/hwui/jni/JvmErrorReporter.h
@@ -30,7 +30,10 @@
     JvmErrorReporter(JNIEnv* env) { env->GetJavaVM(&mVm); }
 
     virtual void onError(const std::string& message) override {
-        JNIEnv* env = GraphicsJNI::getJNIEnv();
+        JNIEnv* env;
+        if (mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+            LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", mVm);
+        }
         jniThrowException(env, "java/lang/IllegalStateException", message.c_str());
     }
 
diff --git a/libs/hwui/jni/Mesh.cpp b/libs/hwui/jni/Mesh.cpp
deleted file mode 100644
index b13d9ba..0000000
--- a/libs/hwui/jni/Mesh.cpp
+++ /dev/null
@@ -1,227 +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.
- */
-
-#include <GLES/gl.h>
-#include <Mesh.h>
-#include <SkMesh.h>
-
-#include "GraphicsJNI.h"
-#include "graphics_jni_helpers.h"
-
-namespace android {
-
-sk_sp<SkMesh::VertexBuffer> genVertexBuffer(JNIEnv* env, jobject buffer, int size,
-                                            jboolean isDirect) {
-    auto buff = ScopedJavaNioBuffer(env, buffer, size, isDirect);
-    auto vertexBuffer = SkMesh::MakeVertexBuffer(nullptr, buff.data(), size);
-    return vertexBuffer;
-}
-
-sk_sp<SkMesh::IndexBuffer> genIndexBuffer(JNIEnv* env, jobject buffer, int size,
-                                          jboolean isDirect) {
-    auto buff = ScopedJavaNioBuffer(env, buffer, size, isDirect);
-    auto indexBuffer = SkMesh::MakeIndexBuffer(nullptr, buff.data(), size);
-    return indexBuffer;
-}
-
-static jlong make(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject vertexBuffer,
-                  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);
-    auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
-    auto meshResult = SkMesh::Make(
-            skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset,
-            SkData::MakeWithCopy(skMeshSpec->uniforms().data(), skMeshSpec->uniformSize()), skRect);
-
-    if (!meshResult.error.isEmpty()) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", meshResult.error.c_str());
-    }
-
-    auto meshPtr = std::make_unique<MeshWrapper>(
-            MeshWrapper{meshResult.mesh, MeshUniformBuilder(skMeshSpec)});
-    return reinterpret_cast<jlong>(meshPtr.release());
-}
-
-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, 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);
-    sk_sp<SkMesh::IndexBuffer> skIndexBuffer =
-            genIndexBuffer(env, indexBuffer, indexCount * gIndexByteSize, isIndexDirect);
-    auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
-
-    auto meshResult = SkMesh::MakeIndexed(
-            skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset,
-            skIndexBuffer, indexCount, indexOffset,
-            SkData::MakeWithCopy(skMeshSpec->uniforms().data(), skMeshSpec->uniformSize()), skRect);
-
-    if (!meshResult.error.isEmpty()) {
-        jniThrowException(env, "java/lang/IllegalArgumentException", meshResult.error.c_str());
-    }
-    auto meshPtr = std::make_unique<MeshWrapper>(
-            MeshWrapper{meshResult.mesh, MeshUniformBuilder(skMeshSpec)});
-    return reinterpret_cast<jlong>(meshPtr.release());
-}
-
-static void updateMesh(JNIEnv* env, jobject, jlong meshWrapper, jboolean indexed) {
-    auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
-    auto mesh = wrapper->mesh;
-    if (indexed) {
-        wrapper->mesh = SkMesh::MakeIndexed(sk_ref_sp(mesh.spec()), mesh.mode(),
-                                            sk_ref_sp(mesh.vertexBuffer()), mesh.vertexCount(),
-                                            mesh.vertexOffset(), sk_ref_sp(mesh.indexBuffer()),
-                                            mesh.indexCount(), mesh.indexOffset(),
-                                            wrapper->builder.fUniforms, mesh.bounds())
-                                .mesh;
-    } else {
-        wrapper->mesh = SkMesh::Make(sk_ref_sp(mesh.spec()), mesh.mode(),
-                                     sk_ref_sp(mesh.vertexBuffer()), mesh.vertexCount(),
-                                     mesh.vertexOffset(), wrapper->builder.fUniforms, mesh.bounds())
-                                .mesh;
-    }
-}
-
-static inline int ThrowIAEFmt(JNIEnv* env, const char* fmt, ...) {
-    va_list args;
-    va_start(args, fmt);
-    int ret = jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", fmt, args);
-    va_end(args);
-    return ret;
-}
-
-static bool isIntUniformType(const SkRuntimeEffect::Uniform::Type& type) {
-    switch (type) {
-        case SkRuntimeEffect::Uniform::Type::kFloat:
-        case SkRuntimeEffect::Uniform::Type::kFloat2:
-        case SkRuntimeEffect::Uniform::Type::kFloat3:
-        case SkRuntimeEffect::Uniform::Type::kFloat4:
-        case SkRuntimeEffect::Uniform::Type::kFloat2x2:
-        case SkRuntimeEffect::Uniform::Type::kFloat3x3:
-        case SkRuntimeEffect::Uniform::Type::kFloat4x4:
-            return false;
-        case SkRuntimeEffect::Uniform::Type::kInt:
-        case SkRuntimeEffect::Uniform::Type::kInt2:
-        case SkRuntimeEffect::Uniform::Type::kInt3:
-        case SkRuntimeEffect::Uniform::Type::kInt4:
-            return true;
-    }
-}
-
-static void nativeUpdateFloatUniforms(JNIEnv* env, MeshUniformBuilder* builder,
-                                      const char* uniformName, const float values[], int count,
-                                      bool isColor) {
-    MeshUniformBuilder::MeshUniform uniform = builder->uniform(uniformName);
-    if (uniform.fVar == nullptr) {
-        ThrowIAEFmt(env, "unable to find uniform named %s", uniformName);
-    } else if (isColor != ((uniform.fVar->flags & SkRuntimeEffect::Uniform::kColor_Flag) != 0)) {
-        if (isColor) {
-            jniThrowExceptionFmt(
-                    env, "java/lang/IllegalArgumentException",
-                    "attempting to set a color uniform using the non-color specific APIs: %s %x",
-                    uniformName, uniform.fVar->flags);
-        } else {
-            ThrowIAEFmt(env,
-                        "attempting to set a non-color uniform using the setColorUniform APIs: %s",
-                        uniformName);
-        }
-    } else if (isIntUniformType(uniform.fVar->type)) {
-        ThrowIAEFmt(env, "attempting to set a int uniform using the setUniform APIs: %s",
-                    uniformName);
-    } else if (!uniform.set<float>(values, count)) {
-        ThrowIAEFmt(env, "mismatch in byte size for uniform [expected: %zu actual: %zu]",
-                    uniform.fVar->sizeInBytes(), sizeof(float) * count);
-    }
-}
-
-static void updateFloatUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
-                                jfloat value1, jfloat value2, jfloat value3, jfloat value4,
-                                jint count) {
-    auto* wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
-    ScopedUtfChars name(env, uniformName);
-    const float values[4] = {value1, value2, value3, value4};
-    nativeUpdateFloatUniforms(env, &wrapper->builder, name.c_str(), values, count, false);
-}
-
-static void updateFloatArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring jUniformName,
-                                     jfloatArray jvalues, jboolean isColor) {
-    auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
-    ScopedUtfChars name(env, jUniformName);
-    AutoJavaFloatArray autoValues(env, jvalues, 0, kRO_JNIAccess);
-    nativeUpdateFloatUniforms(env, &wrapper->builder, name.c_str(), autoValues.ptr(),
-                              autoValues.length(), isColor);
-}
-
-static void nativeUpdateIntUniforms(JNIEnv* env, MeshUniformBuilder* builder,
-                                    const char* uniformName, const int values[], int count) {
-    MeshUniformBuilder::MeshUniform uniform = builder->uniform(uniformName);
-    if (uniform.fVar == nullptr) {
-        ThrowIAEFmt(env, "unable to find uniform named %s", uniformName);
-    } else if (!isIntUniformType(uniform.fVar->type)) {
-        ThrowIAEFmt(env, "attempting to set a non-int uniform using the setIntUniform APIs: %s",
-                    uniformName);
-    } else if (!uniform.set<int>(values, count)) {
-        ThrowIAEFmt(env, "mismatch in byte size for uniform [expected: %zu actual: %zu]",
-                    uniform.fVar->sizeInBytes(), sizeof(float) * count);
-    }
-}
-
-static void updateIntUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
-                              jint value1, jint value2, jint value3, jint value4, jint count) {
-    auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
-    ScopedUtfChars name(env, uniformName);
-    const int values[4] = {value1, value2, value3, value4};
-    nativeUpdateIntUniforms(env, &wrapper->builder, name.c_str(), values, count);
-}
-
-static void updateIntArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
-                                   jintArray values) {
-    auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper);
-    ScopedUtfChars name(env, uniformName);
-    AutoJavaIntArray autoValues(env, values, 0);
-    nativeUpdateIntUniforms(env, &wrapper->builder, name.c_str(), autoValues.ptr(),
-                            autoValues.length());
-}
-
-static void MeshWrapper_destroy(MeshWrapper* wrapper) {
-    delete wrapper;
-}
-
-static jlong getMeshFinalizer(JNIEnv*, jobject) {
-    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&MeshWrapper_destroy));
-}
-
-static const JNINativeMethod gMeshMethods[] = {
-        {"nativeGetFinalizer", "()J", (void*)getMeshFinalizer},
-        {"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},
-        {"nativeUpdateUniforms", "(JLjava/lang/String;FFFFI)V", (void*)updateFloatUniforms},
-        {"nativeUpdateUniforms", "(JLjava/lang/String;[I)V", (void*)updateIntArrayUniforms},
-        {"nativeUpdateUniforms", "(JLjava/lang/String;IIIII)V", (void*)updateIntUniforms}};
-
-int register_android_graphics_Mesh(JNIEnv* env) {
-    android::RegisterMethodsOrDie(env, "android/graphics/Mesh", gMeshMethods, NELEM(gMeshMethods));
-    return 0;
-}
-
-}  // namespace android
diff --git a/libs/hwui/jni/Mesh.h b/libs/hwui/jni/Mesh.h
deleted file mode 100644
index 61c2260..0000000
--- a/libs/hwui/jni/Mesh.h
+++ /dev/null
@@ -1,265 +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.
- */
-
-#ifndef FRAMEWORKS_BASE_LIBS_HWUI_JNI_MESH_H_
-#define FRAMEWORKS_BASE_LIBS_HWUI_JNI_MESH_H_
-
-#include <SkMesh.h>
-#include <jni.h>
-
-#include <log/log.h>
-#include <utility>
-
-#include "graphics_jni_helpers.h"
-
-#define gIndexByteSize 2
-
-// A smart pointer that provides read only access to Java.nio.Buffer. This handles both
-// direct and indrect buffers, allowing access to the underlying data in both
-// situations. If passed a null buffer, we will throw NullPointerException,
-// and c_data will return nullptr.
-//
-// This class draws from com_google_android_gles_jni_GLImpl.cpp for Buffer to void *
-// conversion.
-class ScopedJavaNioBuffer {
-public:
-    ScopedJavaNioBuffer(JNIEnv* env, jobject buffer, jint size, jboolean isDirect)
-            : mEnv(env), mBuffer(buffer) {
-        if (buffer == nullptr) {
-            mDataBase = nullptr;
-            mData = nullptr;
-            jniThrowNullPointerException(env);
-        } else {
-            mArray = (jarray) nullptr;
-            if (isDirect) {
-                mData = getDirectBufferPointer(mEnv, mBuffer);
-            } else {
-                mData = setIndirectData(size);
-            }
-        }
-    }
-
-    ScopedJavaNioBuffer(ScopedJavaNioBuffer&& rhs) noexcept { *this = std::move(rhs); }
-
-    ~ScopedJavaNioBuffer() { reset(); }
-
-    void reset() {
-        if (mDataBase) {
-            releasePointer(mEnv, mArray, mDataBase, JNI_FALSE);
-            mDataBase = nullptr;
-        }
-    }
-
-    ScopedJavaNioBuffer& operator=(ScopedJavaNioBuffer&& rhs) noexcept {
-        if (this != &rhs) {
-            reset();
-
-            mEnv = rhs.mEnv;
-            mBuffer = rhs.mBuffer;
-            mDataBase = rhs.mDataBase;
-            mData = rhs.mData;
-            mArray = rhs.mArray;
-            rhs.mEnv = nullptr;
-            rhs.mData = nullptr;
-            rhs.mBuffer = nullptr;
-            rhs.mArray = nullptr;
-            rhs.mDataBase = nullptr;
-        }
-        return *this;
-    }
-
-    const void* data() const { return mData; }
-
-private:
-    /**
-     * This code is taken and modified from com_google_android_gles_jni_GLImpl.cpp to extract data
-     * from a java.nio.Buffer.
-     */
-    void* getDirectBufferPointer(JNIEnv* env, jobject buffer) {
-        if (buffer == nullptr) {
-            return nullptr;
-        }
-
-        jint position;
-        jint limit;
-        jint elementSizeShift;
-        jlong pointer;
-        pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
-        if (pointer == 0) {
-            jniThrowException(mEnv, "java/lang/IllegalArgumentException",
-                              "Must use a native order direct Buffer");
-            return nullptr;
-        }
-        pointer += position << elementSizeShift;
-        return reinterpret_cast<void*>(pointer);
-    }
-
-    static void releasePointer(JNIEnv* env, jarray array, void* data, jboolean commit) {
-        env->ReleasePrimitiveArrayCritical(array, data, commit ? 0 : JNI_ABORT);
-    }
-
-    static void* getPointer(JNIEnv* env, jobject buffer, jarray* array, jint* remaining,
-                            jint* offset) {
-        jint position;
-        jint limit;
-        jint elementSizeShift;
-
-        jlong pointer;
-        pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
-        *remaining = (limit - position) << elementSizeShift;
-        if (pointer != 0L) {
-            *array = nullptr;
-            pointer += position << elementSizeShift;
-            return reinterpret_cast<void*>(pointer);
-        }
-
-        *array = jniGetNioBufferBaseArray(env, buffer);
-        *offset = jniGetNioBufferBaseArrayOffset(env, buffer);
-        return nullptr;
-    }
-
-    /**
-     * This is a copy of
-     * static void android_glBufferData__IILjava_nio_Buffer_2I
-     * from com_google_android_gles_jni_GLImpl.cpp
-     */
-    void* setIndirectData(jint size) {
-        jint exception;
-        const char* exceptionType;
-        const char* exceptionMessage;
-        jint bufferOffset = (jint)0;
-        jint remaining;
-        void* tempData;
-
-        if (mBuffer) {
-            tempData =
-                    (void*)getPointer(mEnv, mBuffer, (jarray*)&mArray, &remaining, &bufferOffset);
-            if (remaining < size) {
-                exception = 1;
-                exceptionType = "java/lang/IllegalArgumentException";
-                exceptionMessage = "remaining() < size < needed";
-                goto exit;
-            }
-        }
-        if (mBuffer && tempData == nullptr) {
-            mDataBase = (char*)mEnv->GetPrimitiveArrayCritical(mArray, (jboolean*)0);
-            tempData = (void*)(mDataBase + bufferOffset);
-        }
-        return tempData;
-    exit:
-        if (mArray) {
-            releasePointer(mEnv, mArray, (void*)(mDataBase), JNI_FALSE);
-        }
-        if (exception) {
-            jniThrowException(mEnv, exceptionType, exceptionMessage);
-        }
-        return nullptr;
-    }
-
-    JNIEnv* mEnv;
-
-    // Java Buffer data
-    void* mData;
-    jobject mBuffer;
-
-    // Indirect Buffer Data
-    jarray mArray;
-    char* mDataBase;
-};
-
-class MeshUniformBuilder {
-public:
-    struct MeshUniform {
-        template <typename T>
-        std::enable_if_t<std::is_trivially_copyable<T>::value, MeshUniform> operator=(
-                const T& val) {
-            if (!fVar) {
-                LOG_FATAL("Assigning to missing variable");
-            } else if (sizeof(val) != fVar->sizeInBytes()) {
-                LOG_FATAL("Incorrect value size");
-            } else {
-                void* dst = reinterpret_cast<void*>(
-                    reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
-                memcpy(dst, &val, sizeof(val));
-            }
-        }
-
-        MeshUniform& operator=(const SkMatrix& val) {
-            if (!fVar) {
-                LOG_FATAL("Assigning to missing variable");
-            } else if (fVar->sizeInBytes() != 9 * sizeof(float)) {
-                LOG_FATAL("Incorrect value size");
-            } else {
-                float* data = reinterpret_cast<float*>(
-                    reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
-                data[0] = val.get(0);
-                data[1] = val.get(3);
-                data[2] = val.get(6);
-                data[3] = val.get(1);
-                data[4] = val.get(4);
-                data[5] = val.get(7);
-                data[6] = val.get(2);
-                data[7] = val.get(5);
-                data[8] = val.get(8);
-            }
-            return *this;
-        }
-
-        template <typename T>
-        bool set(const T val[], const int count) {
-            static_assert(std::is_trivially_copyable<T>::value, "Value must be trivial copyable");
-            if (!fVar) {
-                LOG_FATAL("Assigning to missing variable");
-                return false;
-            } else if (sizeof(T) * count != fVar->sizeInBytes()) {
-                LOG_FATAL("Incorrect value size");
-                return false;
-            } else {
-                void* dst = reinterpret_cast<void*>(
-                    reinterpret_cast<uint8_t*>(fOwner->writableUniformData()) + fVar->offset);
-                memcpy(dst, val, sizeof(T) * count);
-            }
-            return true;
-        }
-
-        MeshUniformBuilder* fOwner;
-        const SkRuntimeEffect::Uniform* fVar;
-    };
-    MeshUniform uniform(std::string_view name) { return {this, fMeshSpec->findUniform(name)}; }
-
-    explicit MeshUniformBuilder(sk_sp<SkMeshSpecification> meshSpec) {
-        fMeshSpec = sk_sp(meshSpec);
-        fUniforms = (SkData::MakeZeroInitialized(meshSpec->uniformSize()));
-    }
-
-    sk_sp<SkData> fUniforms;
-
-private:
-    void* writableUniformData() {
-        if (!fUniforms->unique()) {
-            fUniforms = SkData::MakeWithCopy(fUniforms->data(), fUniforms->size());
-        }
-        return fUniforms->writable_data();
-    }
-
-    sk_sp<SkMeshSpecification> fMeshSpec;
-};
-
-struct MeshWrapper {
-    SkMesh mesh;
-    MeshUniformBuilder builder;
-};
-#endif  // FRAMEWORKS_BASE_LIBS_HWUI_JNI_MESH_H_
diff --git a/libs/hwui/jni/Path.cpp b/libs/hwui/jni/Path.cpp
index 3694ce0..a5e0476 100644
--- a/libs/hwui/jni/Path.cpp
+++ b/libs/hwui/jni/Path.cpp
@@ -182,11 +182,7 @@
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPathDirection dir = static_cast<SkPathDirection>(dirHandle);
         AutoJavaFloatArray  afa(env, array, 8);
-#ifdef SK_SCALAR_IS_FLOAT
         const float* src = afa.ptr();
-#else
-        #error Need to convert float array to SkScalar array before calling the following function.
-#endif
         obj->addRoundRect(rect, src, dir);
     }
 
diff --git a/libs/hwui/jni/PathEffect.cpp b/libs/hwui/jni/PathEffect.cpp
index f99bef7..3dbe1a6 100644
--- a/libs/hwui/jni/PathEffect.cpp
+++ b/libs/hwui/jni/PathEffect.cpp
@@ -35,11 +35,7 @@
                                       jfloatArray intervalArray, jfloat phase) {
         AutoJavaFloatArray autoInterval(env, intervalArray);
         int         count = autoInterval.length() & ~1;  // even number
-#ifdef SK_SCALAR_IS_FLOAT
-        SkScalar*   intervals = autoInterval.ptr();
-#else
-        #error Need to convert float array to SkScalar array before calling the following function.
-#endif
+        SkScalar* intervals = autoInterval.ptr();
         SkPathEffect* effect = SkDashPathEffect::Make(intervals, count, phase).release();
         return reinterpret_cast<jlong>(effect);
     }
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index 8a0db1c..75d45e5 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -52,12 +52,7 @@
 static jint Color_HSVToColor(JNIEnv* env, jobject, jint alpha, jfloatArray hsvArray)
 {
     AutoJavaFloatArray  autoHSV(env, hsvArray, 3);
-#ifdef SK_SCALAR_IS_FLOAT
-    SkScalar*   hsv = autoHSV.ptr();
-#else
-    #error Need to convert float array to SkScalar array before calling the following function.
-#endif
-
+    SkScalar* hsv = autoHSV.ptr();
     return static_cast<jint>(SkHSVToColor(alpha, hsv));
 }
 
@@ -149,11 +144,7 @@
     std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);
 
     AutoJavaFloatArray autoPos(env, posArray, colors.size());
-#ifdef SK_SCALAR_IS_FLOAT
     SkScalar* pos = autoPos.ptr();
-#else
-    #error Need to convert float array to SkScalar array before calling the following function.
-#endif
 
     sk_sp<SkShader> shader(SkGradientShader::MakeLinear(pts, &colors[0],
                 GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
@@ -193,11 +184,7 @@
     std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);
 
     AutoJavaFloatArray autoPos(env, posArray, colors.size());
-#ifdef SK_SCALAR_IS_FLOAT
     SkScalar* pos = autoPos.ptr();
-#else
-    #error Need to convert float array to SkScalar array before calling the following function.
-#endif
 
     auto colorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
     auto skTileMode = static_cast<SkTileMode>(tileMode);
@@ -225,11 +212,7 @@
     std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);
 
     AutoJavaFloatArray autoPos(env, jpositions, colors.size());
-#ifdef SK_SCALAR_IS_FLOAT
     SkScalar* pos = autoPos.ptr();
-#else
-    #error Need to convert float array to SkScalar array before calling the following function.
-#endif
 
     sk_sp<SkShader> shader = SkGradientShader::MakeSweep(x, y, &colors[0],
             GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
diff --git a/libs/hwui/jni/android_graphics_Canvas.cpp b/libs/hwui/jni/android_graphics_Canvas.cpp
index 8a4d4e1..8ba7503 100644
--- a/libs/hwui/jni/android_graphics_Canvas.cpp
+++ b/libs/hwui/jni/android_graphics_Canvas.cpp
@@ -21,7 +21,6 @@
 #else
 #define __ANDROID_API_P__ 28
 #endif
-#include <Mesh.h>
 #include <androidfw/ResourceTypes.h>
 #include <hwui/Canvas.h>
 #include <hwui/Paint.h>
@@ -446,10 +445,10 @@
 
 static void drawMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong meshHandle, jint modeHandle,
                      jlong paintHandle) {
-    const SkMesh mesh = reinterpret_cast<MeshWrapper*>(meshHandle)->mesh;
+    const Mesh* mesh = reinterpret_cast<Mesh*>(meshHandle);
     SkBlendMode blendMode = static_cast<SkBlendMode>(modeHandle);
-    SkPaint* paint = reinterpret_cast<Paint*>(paintHandle);
-    get_canvas(canvasHandle)->drawMesh(mesh, SkBlender::Mode(blendMode), *paint);
+    Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+    get_canvas(canvasHandle)->drawMesh(*mesh, SkBlender::Mode(blendMode), *paint);
 }
 
 static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
diff --git a/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
index 3e453e6..ae22213 100644
--- a/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
@@ -49,7 +49,7 @@
     auto globalCallbackRef =
             std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(releaseCallback));
     return [globalCallbackRef](android::base::unique_fd&& fd, int status) {
-        GraphicsJNI::getJNIEnv()->CallStaticVoidMethod(
+        globalCallbackRef->env()->CallStaticVoidMethod(
                 gHardwareBufferRendererClassInfo.clazz,
                 gHardwareBufferRendererClassInfo.invokeRenderCallback, globalCallbackRef->object(),
                 reinterpret_cast<jint>(fd.release()), reinterpret_cast<jint>(status));
@@ -172,7 +172,8 @@
 int register_android_graphics_HardwareBufferRenderer(JNIEnv* env) {
     jclass hardwareBufferRendererClazz =
             FindClassOrDie(env, "android/graphics/HardwareBufferRenderer");
-    gHardwareBufferRendererClassInfo.clazz = hardwareBufferRendererClazz;
+    gHardwareBufferRendererClassInfo.clazz =
+            reinterpret_cast<jclass>(env->NewGlobalRef(hardwareBufferRendererClazz));
     gHardwareBufferRendererClassInfo.invokeRenderCallback =
             GetStaticMethodIDOrDie(env, hardwareBufferRendererClazz, "invokeRenderCallback",
                                    "(Ljava/util/function/Consumer;II)V");
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index d6aad7d..6a7411f 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -94,12 +94,21 @@
     jmethodID getDestinationBitmap;
 } gCopyRequest;
 
+static JNIEnv* getenv(JavaVM* vm) {
+    JNIEnv* env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        LOG_ALWAYS_FATAL("Failed to get JNIEnv for JavaVM: %p", vm);
+    }
+    return env;
+}
+
 typedef ANativeWindow* (*ANW_fromSurface)(JNIEnv* env, jobject surface);
 ANW_fromSurface fromSurface;
 
 class FrameCommitWrapper : public LightRefBase<FrameCommitWrapper> {
 public:
     explicit FrameCommitWrapper(JNIEnv* env, jobject jobject) {
+        env->GetJavaVM(&mVm);
         mObject = env->NewGlobalRef(jobject);
         LOG_ALWAYS_FATAL_IF(!mObject, "Failed to make global ref");
     }
@@ -109,18 +118,19 @@
     void onFrameCommit(bool didProduceBuffer) {
         if (mObject) {
             ATRACE_FORMAT("frameCommit success=%d", didProduceBuffer);
-            GraphicsJNI::getJNIEnv()->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit,
-                                                     didProduceBuffer);
+            getenv(mVm)->CallVoidMethod(mObject, gFrameCommitCallback.onFrameCommit,
+                                        didProduceBuffer);
             releaseObject();
         }
     }
 
 private:
+    JavaVM* mVm;
     jobject mObject;
 
     void releaseObject() {
         if (mObject) {
-            GraphicsJNI::getJNIEnv()->DeleteGlobalRef(mObject);
+            getenv(mVm)->DeleteGlobalRef(mObject);
             mObject = nullptr;
         }
     }
@@ -541,10 +551,9 @@
         auto pictureState = std::make_shared<PictureCaptureState>();
         proxy->setPictureCapturedCallback([globalCallbackRef,
                                            pictureState](sk_sp<SkPicture>&& picture) {
-            JNIEnv* env = GraphicsJNI::getJNIEnv();
             Picture* wrapper = new PictureWrapper{std::move(picture), pictureState};
-            env->CallStaticVoidMethod(gHardwareRenderer.clazz,
-                    gHardwareRenderer.invokePictureCapturedCallback,
+            globalCallbackRef->env()->CallStaticVoidMethod(
+                    gHardwareRenderer.clazz, gHardwareRenderer.invokePictureCapturedCallback,
                     static_cast<jlong>(reinterpret_cast<intptr_t>(wrapper)),
                     globalCallbackRef->object());
         });
@@ -561,16 +570,14 @@
         LOG_ALWAYS_FATAL_IF(env->GetJavaVM(&vm) != JNI_OK, "Unable to get Java VM");
         auto globalCallbackRef = std::make_shared<JGlobalRefHolder>(
                 vm, env->NewGlobalRef(aSurfaceTransactionCallback));
-        proxy->setASurfaceTransactionCallback(
-                [globalCallbackRef](int64_t transObj, int64_t scObj, int64_t frameNr) -> bool {
-                    JNIEnv* env = GraphicsJNI::getJNIEnv();
-                    jboolean ret = env->CallBooleanMethod(
-                            globalCallbackRef->object(),
-                            gASurfaceTransactionCallback.onMergeTransaction,
-                            static_cast<jlong>(transObj), static_cast<jlong>(scObj),
-                            static_cast<jlong>(frameNr));
-                    return ret;
-                });
+        proxy->setASurfaceTransactionCallback([globalCallbackRef](int64_t transObj, int64_t scObj,
+                                                                  int64_t frameNr) -> bool {
+            jboolean ret = globalCallbackRef->env()->CallBooleanMethod(
+                    globalCallbackRef->object(), gASurfaceTransactionCallback.onMergeTransaction,
+                    static_cast<jlong>(transObj), static_cast<jlong>(scObj),
+                    static_cast<jlong>(frameNr));
+            return ret;
+        });
     }
 }
 
@@ -585,9 +592,8 @@
         auto globalCallbackRef =
                 std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
         proxy->setPrepareSurfaceControlForWebviewCallback([globalCallbackRef]() {
-            JNIEnv* env = GraphicsJNI::getJNIEnv();
-            env->CallVoidMethod(globalCallbackRef->object(),
-                                gPrepareSurfaceControlForWebviewCallback.prepare);
+            globalCallbackRef->env()->CallVoidMethod(
+                    globalCallbackRef->object(), gPrepareSurfaceControlForWebviewCallback.prepare);
         });
     }
 }
@@ -604,7 +610,7 @@
                 env->NewGlobalRef(frameCallback));
         proxy->setFrameCallback([globalCallbackRef](int32_t syncResult,
                                                     int64_t frameNr) -> std::function<void(bool)> {
-            JNIEnv* env = GraphicsJNI::getJNIEnv();
+            JNIEnv* env = globalCallbackRef->env();
             ScopedLocalRef<jobject> frameCommitCallback(
                     env, env->CallObjectMethod(
                                  globalCallbackRef->object(), gFrameDrawingCallback.onFrameDraw,
@@ -643,9 +649,8 @@
         auto globalCallbackRef =
                 std::make_shared<JGlobalRefHolder>(vm, env->NewGlobalRef(callback));
         proxy->setFrameCompleteCallback([globalCallbackRef]() {
-            JNIEnv* env = GraphicsJNI::getJNIEnv();
-            env->CallVoidMethod(globalCallbackRef->object(),
-                                gFrameCompleteCallback.onFrameComplete);
+            globalCallbackRef->env()->CallVoidMethod(globalCallbackRef->object(),
+                                                     gFrameCompleteCallback.onFrameComplete);
         });
     }
 }
@@ -656,8 +661,7 @@
             : CopyRequest(srcRect), mRefHolder(vm, jCopyRequest) {}
 
     virtual SkBitmap getDestinationBitmap(int srcWidth, int srcHeight) override {
-        JNIEnv* env = GraphicsJNI::getJNIEnv();
-        jlong bitmapPtr = env->CallLongMethod(
+        jlong bitmapPtr = mRefHolder.env()->CallLongMethod(
                 mRefHolder.object(), gCopyRequest.getDestinationBitmap, srcWidth, srcHeight);
         SkBitmap bitmap;
         bitmap::toBitmap(bitmapPtr).getSkBitmap(&bitmap);
@@ -665,9 +669,8 @@
     }
 
     virtual void onCopyFinished(CopyResult result) override {
-        JNIEnv* env = GraphicsJNI::getJNIEnv();
-        env->CallVoidMethod(mRefHolder.object(), gCopyRequest.onCopyFinished,
-                            static_cast<jint>(result));
+        mRefHolder.env()->CallVoidMethod(mRefHolder.object(), gCopyRequest.onCopyFinished,
+                                         static_cast<jint>(result));
     }
 
 private:
diff --git a/libs/hwui/jni/android_graphics_Matrix.cpp b/libs/hwui/jni/android_graphics_Matrix.cpp
index cf6702e..ca667b0 100644
--- a/libs/hwui/jni/android_graphics_Matrix.cpp
+++ b/libs/hwui/jni/android_graphics_Matrix.cpp
@@ -23,8 +23,6 @@
 
 static_assert(sizeof(SkMatrix) == 40, "Unexpected sizeof(SkMatrix), "
         "update size in Matrix.java#NATIVE_ALLOCATION_SIZE and here");
-static_assert(SK_SCALAR_IS_FLOAT, "SK_SCALAR_IS_FLOAT is false, "
-        "only float scalar is supported");
 
 class SkMatrixGlue {
 public:
diff --git a/libs/hwui/jni/android_graphics_Mesh.cpp b/libs/hwui/jni/android_graphics_Mesh.cpp
new file mode 100644
index 0000000..04339dc
--- /dev/null
+++ b/libs/hwui/jni/android_graphics_Mesh.cpp
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <GrDirectContext.h>
+#include <Mesh.h>
+#include <SkMesh.h>
+#include <jni.h>
+#include <log/log.h>
+
+#include <utility>
+
+#include "GraphicsJNI.h"
+#include "graphics_jni_helpers.h"
+
+#define gIndexByteSize 2
+
+// A smart pointer that provides read only access to Java.nio.Buffer. This handles both
+// direct and indrect buffers, allowing access to the underlying data in both
+// situations. If passed a null buffer, we will throw NullPointerException,
+// and c_data will return nullptr.
+//
+// This class draws from com_google_android_gles_jni_GLImpl.cpp for Buffer to void *
+// conversion.
+class ScopedJavaNioBuffer {
+public:
+    ScopedJavaNioBuffer(JNIEnv* env, jobject buffer, size_t size, jboolean isDirect)
+            : mEnv(env), mBuffer(buffer) {
+        if (buffer == nullptr) {
+            mDataBase = nullptr;
+            mData = nullptr;
+            jniThrowNullPointerException(env);
+        } else {
+            mArray = (jarray) nullptr;
+            if (isDirect) {
+                mData = getDirectBufferPointer(mEnv, mBuffer);
+            } else {
+                mData = setIndirectData(size);
+            }
+        }
+    }
+
+    ScopedJavaNioBuffer(ScopedJavaNioBuffer&& rhs) noexcept { *this = std::move(rhs); }
+
+    ~ScopedJavaNioBuffer() { reset(); }
+
+    void reset() {
+        if (mDataBase) {
+            releasePointer(mEnv, mArray, mDataBase, JNI_FALSE);
+            mDataBase = nullptr;
+        }
+    }
+
+    ScopedJavaNioBuffer& operator=(ScopedJavaNioBuffer&& rhs) noexcept {
+        if (this != &rhs) {
+            reset();
+
+            mEnv = rhs.mEnv;
+            mBuffer = rhs.mBuffer;
+            mDataBase = rhs.mDataBase;
+            mData = rhs.mData;
+            mArray = rhs.mArray;
+            rhs.mEnv = nullptr;
+            rhs.mData = nullptr;
+            rhs.mBuffer = nullptr;
+            rhs.mArray = nullptr;
+            rhs.mDataBase = nullptr;
+        }
+        return *this;
+    }
+
+    const void* data() const { return mData; }
+
+private:
+    /**
+     * This code is taken and modified from com_google_android_gles_jni_GLImpl.cpp to extract data
+     * from a java.nio.Buffer.
+     */
+    void* getDirectBufferPointer(JNIEnv* env, jobject buffer) {
+        if (buffer == nullptr) {
+            return nullptr;
+        }
+
+        jint position;
+        jint limit;
+        jint elementSizeShift;
+        jlong pointer;
+        pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
+        if (pointer == 0) {
+            jniThrowException(mEnv, "java/lang/IllegalArgumentException",
+                              "Must use a native order direct Buffer");
+            return nullptr;
+        }
+        pointer += position << elementSizeShift;
+        return reinterpret_cast<void*>(pointer);
+    }
+
+    static void releasePointer(JNIEnv* env, jarray array, void* data, jboolean commit) {
+        env->ReleasePrimitiveArrayCritical(array, data, commit ? 0 : JNI_ABORT);
+    }
+
+    static void* getPointer(JNIEnv* env, jobject buffer, jarray* array, jint* remaining,
+                            jint* offset) {
+        jint position;
+        jint limit;
+        jint elementSizeShift;
+
+        jlong pointer;
+        pointer = jniGetNioBufferFields(env, buffer, &position, &limit, &elementSizeShift);
+        *remaining = (limit - position) << elementSizeShift;
+        if (pointer != 0L) {
+            *array = nullptr;
+            pointer += position << elementSizeShift;
+            return reinterpret_cast<void*>(pointer);
+        }
+
+        *array = jniGetNioBufferBaseArray(env, buffer);
+        *offset = jniGetNioBufferBaseArrayOffset(env, buffer);
+        return nullptr;
+    }
+
+    /**
+     * This is a copy of
+     * static void android_glBufferData__IILjava_nio_Buffer_2I
+     * from com_google_android_gles_jni_GLImpl.cpp
+     */
+    void* setIndirectData(size_t size) {
+        jint exception;
+        const char* exceptionType;
+        const char* exceptionMessage;
+        jint bufferOffset = (jint)0;
+        jint remaining;
+        void* tempData;
+
+        if (mBuffer) {
+            tempData =
+                    (void*)getPointer(mEnv, mBuffer, (jarray*)&mArray, &remaining, &bufferOffset);
+            if (remaining < size) {
+                exception = 1;
+                exceptionType = "java/lang/IllegalArgumentException";
+                exceptionMessage = "remaining() < size < needed";
+                goto exit;
+            }
+        }
+        if (mBuffer && tempData == nullptr) {
+            mDataBase = (char*)mEnv->GetPrimitiveArrayCritical(mArray, (jboolean*)0);
+            tempData = (void*)(mDataBase + bufferOffset);
+        }
+        return tempData;
+    exit:
+        if (mArray) {
+            releasePointer(mEnv, mArray, (void*)(mDataBase), JNI_FALSE);
+        }
+        if (exception) {
+            jniThrowException(mEnv, exceptionType, exceptionMessage);
+        }
+        return nullptr;
+    }
+
+    JNIEnv* mEnv;
+
+    // Java Buffer data
+    void* mData;
+    jobject mBuffer;
+
+    // Indirect Buffer Data
+    jarray mArray;
+    char* mDataBase;
+};
+
+namespace android {
+
+static jlong make(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject vertexBuffer,
+                  jboolean isDirect, jint vertexCount, jint vertexOffset, jfloat left, jfloat top,
+                  jfloat right, jfloat bottom) {
+    auto skMeshSpec = sk_ref_sp(reinterpret_cast<SkMeshSpecification*>(meshSpec));
+    size_t bufferSize = vertexCount * skMeshSpec->stride();
+    auto buff = ScopedJavaNioBuffer(env, vertexBuffer, bufferSize, isDirect);
+    auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
+    auto meshPtr = new Mesh(skMeshSpec, mode, buff.data(), bufferSize, vertexCount, vertexOffset,
+                            std::make_unique<MeshUniformBuilder>(skMeshSpec), skRect);
+    auto [valid, msg] = meshPtr->validate();
+    if (!valid) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", msg.c_str());
+    }
+    return reinterpret_cast<jlong>(meshPtr);
+}
+
+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, jfloat left, jfloat top, jfloat right, jfloat bottom) {
+    auto skMeshSpec = sk_ref_sp(reinterpret_cast<SkMeshSpecification*>(meshSpec));
+    auto vertexBufferSize = vertexCount * skMeshSpec->stride();
+    auto indexBufferSize = indexCount * gIndexByteSize;
+    auto vBuf = ScopedJavaNioBuffer(env, vertexBuffer, vertexBufferSize, isVertexDirect);
+    auto iBuf = ScopedJavaNioBuffer(env, indexBuffer, indexBufferSize, isIndexDirect);
+    auto skRect = SkRect::MakeLTRB(left, top, right, bottom);
+    auto meshPtr = new Mesh(skMeshSpec, mode, vBuf.data(), vertexBufferSize, vertexCount,
+                            vertexOffset, iBuf.data(), indexBufferSize, indexCount, indexOffset,
+                            std::make_unique<MeshUniformBuilder>(skMeshSpec), skRect);
+    auto [valid, msg] = meshPtr->validate();
+    if (!valid) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", msg.c_str());
+    }
+
+    return reinterpret_cast<jlong>(meshPtr);
+}
+
+static inline int ThrowIAEFmt(JNIEnv* env, const char* fmt, ...) {
+    va_list args;
+    va_start(args, fmt);
+    int ret = jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", fmt, args);
+    va_end(args);
+    return ret;
+}
+
+static bool isIntUniformType(const SkRuntimeEffect::Uniform::Type& type) {
+    switch (type) {
+        case SkRuntimeEffect::Uniform::Type::kFloat:
+        case SkRuntimeEffect::Uniform::Type::kFloat2:
+        case SkRuntimeEffect::Uniform::Type::kFloat3:
+        case SkRuntimeEffect::Uniform::Type::kFloat4:
+        case SkRuntimeEffect::Uniform::Type::kFloat2x2:
+        case SkRuntimeEffect::Uniform::Type::kFloat3x3:
+        case SkRuntimeEffect::Uniform::Type::kFloat4x4:
+            return false;
+        case SkRuntimeEffect::Uniform::Type::kInt:
+        case SkRuntimeEffect::Uniform::Type::kInt2:
+        case SkRuntimeEffect::Uniform::Type::kInt3:
+        case SkRuntimeEffect::Uniform::Type::kInt4:
+            return true;
+    }
+}
+
+static void nativeUpdateFloatUniforms(JNIEnv* env, MeshUniformBuilder* builder,
+                                      const char* uniformName, const float values[], int count,
+                                      bool isColor) {
+    MeshUniformBuilder::MeshUniform uniform = builder->uniform(uniformName);
+    if (uniform.fVar == nullptr) {
+        ThrowIAEFmt(env, "unable to find uniform named %s", uniformName);
+    } else if (isColor != ((uniform.fVar->flags & SkRuntimeEffect::Uniform::kColor_Flag) != 0)) {
+        if (isColor) {
+            jniThrowExceptionFmt(
+                    env, "java/lang/IllegalArgumentException",
+                    "attempting to set a color uniform using the non-color specific APIs: %s %x",
+                    uniformName, uniform.fVar->flags);
+        } else {
+            ThrowIAEFmt(env,
+                        "attempting to set a non-color uniform using the setColorUniform APIs: %s",
+                        uniformName);
+        }
+    } else if (isIntUniformType(uniform.fVar->type)) {
+        ThrowIAEFmt(env, "attempting to set a int uniform using the setUniform APIs: %s",
+                    uniformName);
+    } else if (!uniform.set<float>(values, count)) {
+        ThrowIAEFmt(env, "mismatch in byte size for uniform [expected: %zu actual: %zu]",
+                    uniform.fVar->sizeInBytes(), sizeof(float) * count);
+    }
+}
+
+static void updateFloatUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
+                                jfloat value1, jfloat value2, jfloat value3, jfloat value4,
+                                jint count) {
+    auto* wrapper = reinterpret_cast<Mesh*>(meshWrapper);
+    ScopedUtfChars name(env, uniformName);
+    const float values[4] = {value1, value2, value3, value4};
+    nativeUpdateFloatUniforms(env, wrapper->uniformBuilder(), name.c_str(), values, count, false);
+    wrapper->markDirty();
+}
+
+static void updateFloatArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring jUniformName,
+                                     jfloatArray jvalues, jboolean isColor) {
+    auto wrapper = reinterpret_cast<Mesh*>(meshWrapper);
+    ScopedUtfChars name(env, jUniformName);
+    AutoJavaFloatArray autoValues(env, jvalues, 0, kRO_JNIAccess);
+    nativeUpdateFloatUniforms(env, wrapper->uniformBuilder(), name.c_str(), autoValues.ptr(),
+                              autoValues.length(), isColor);
+    wrapper->markDirty();
+}
+
+static void nativeUpdateIntUniforms(JNIEnv* env, MeshUniformBuilder* builder,
+                                    const char* uniformName, const int values[], int count) {
+    MeshUniformBuilder::MeshUniform uniform = builder->uniform(uniformName);
+    if (uniform.fVar == nullptr) {
+        ThrowIAEFmt(env, "unable to find uniform named %s", uniformName);
+    } else if (!isIntUniformType(uniform.fVar->type)) {
+        ThrowIAEFmt(env, "attempting to set a non-int uniform using the setIntUniform APIs: %s",
+                    uniformName);
+    } else if (!uniform.set<int>(values, count)) {
+        ThrowIAEFmt(env, "mismatch in byte size for uniform [expected: %zu actual: %zu]",
+                    uniform.fVar->sizeInBytes(), sizeof(float) * count);
+    }
+}
+
+static void updateIntUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
+                              jint value1, jint value2, jint value3, jint value4, jint count) {
+    auto wrapper = reinterpret_cast<Mesh*>(meshWrapper);
+    ScopedUtfChars name(env, uniformName);
+    const int values[4] = {value1, value2, value3, value4};
+    nativeUpdateIntUniforms(env, wrapper->uniformBuilder(), name.c_str(), values, count);
+    wrapper->markDirty();
+}
+
+static void updateIntArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName,
+                                   jintArray values) {
+    auto wrapper = reinterpret_cast<Mesh*>(meshWrapper);
+    ScopedUtfChars name(env, uniformName);
+    AutoJavaIntArray autoValues(env, values, 0);
+    nativeUpdateIntUniforms(env, wrapper->uniformBuilder(), name.c_str(), autoValues.ptr(),
+                            autoValues.length());
+    wrapper->markDirty();
+}
+
+static void MeshWrapper_destroy(Mesh* wrapper) {
+    delete wrapper;
+}
+
+static jlong getMeshFinalizer(JNIEnv*, jobject) {
+    return static_cast<jlong>(reinterpret_cast<uintptr_t>(&MeshWrapper_destroy));
+}
+
+static const JNINativeMethod gMeshMethods[] = {
+        {"nativeGetFinalizer", "()J", (void*)getMeshFinalizer},
+        {"nativeMake", "(JILjava/nio/Buffer;ZIIFFFF)J", (void*)make},
+        {"nativeMakeIndexed", "(JILjava/nio/Buffer;ZIILjava/nio/ShortBuffer;ZIIFFFF)J",
+         (void*)makeIndexed},
+        {"nativeUpdateUniforms", "(JLjava/lang/String;[FZ)V", (void*)updateFloatArrayUniforms},
+        {"nativeUpdateUniforms", "(JLjava/lang/String;FFFFI)V", (void*)updateFloatUniforms},
+        {"nativeUpdateUniforms", "(JLjava/lang/String;[I)V", (void*)updateIntArrayUniforms},
+        {"nativeUpdateUniforms", "(JLjava/lang/String;IIIII)V", (void*)updateIntUniforms}};
+
+int register_android_graphics_Mesh(JNIEnv* env) {
+    android::RegisterMethodsOrDie(env, "android/graphics/Mesh", gMeshMethods, NELEM(gMeshMethods));
+    return 0;
+}
+
+}  // namespace android
\ No newline at end of file
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
index fcfc4f8..af2d3b3 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp
@@ -23,6 +23,7 @@
 #else
 #include "DamageAccumulator.h"
 #endif
+#include "TreeInfo.h"
 #include "VectorDrawable.h"
 #ifdef __ANDROID__
 #include "renderthread/CanvasContext.h"
@@ -102,6 +103,12 @@
         info.prepareTextures = false;
         info.canvasContext.unpinImages();
     }
+
+    auto grContext = info.canvasContext.getGrContext();
+    for (auto mesh : mMeshes) {
+        mesh->updateSkMesh(grContext);
+    }
+
 #endif
 
     bool hasBackwardProjectedNodesHere = false;
@@ -168,6 +175,7 @@
 
     mDisplayList.reset();
 
+    mMeshes.clear();
     mMutableImages.clear();
     mVectorDrawables.clear();
     mAnimatedImages.clear();
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 2a67734..7af31a4 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -18,6 +18,7 @@
 
 #include <deque>
 
+#include "Mesh.h"
 #include "RecordingCanvas.h"
 #include "RenderNodeDrawable.h"
 #include "TreeInfo.h"
@@ -167,6 +168,7 @@
     std::deque<RenderNodeDrawable> mChildNodes;
     std::deque<FunctorDrawable*> mChildFunctors;
     std::vector<SkImage*> mMutableImages;
+    std::vector<const Mesh*> mMeshes;
 
 private:
     std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index e1c8877..3ca7eeb 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -321,6 +321,11 @@
     return 0;
 }
 
+void SkiaRecordingCanvas::drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) {
+    mDisplayList->mMeshes.push_back(&mesh);
+    mRecorder.drawMesh(mesh, blender, paint);
+}
+
 }  // namespace skiapipeline
 }  // namespace uirenderer
 }  // namespace android
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 3fd8fa3..a8e4580 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -81,6 +81,7 @@
     virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
 
     virtual void enableZ(bool enableZ) override;
+    virtual void drawMesh(const Mesh& mesh, sk_sp<SkBlender> blender, const Paint& paint) override;
     virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override;
     virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override;
 
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 5136675..4da4c7f 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -16,9 +16,9 @@
 
 package android.media;
 
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
 
 import android.Manifest;
 import android.annotation.CallbackExecutor;
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index b6ab262..7faa13c 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -16,9 +16,9 @@
 
 package android.media;
 
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
 import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
 
 import android.annotation.CallbackExecutor;
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 38115e1..3f44b09 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -16,9 +16,9 @@
 
 package android.media;
 
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
 import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
 
 import android.annotation.NonNull;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioManagerUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioManagerUnitTest.java
index 76543f4..6089f42 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioManagerUnitTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioManagerUnitTest.java
@@ -17,10 +17,10 @@
 package com.android.mediaframeworktest.unit;
 
 
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
 import static android.media.AudioManager.FX_KEY_CLICK;
 
 import static org.mockito.ArgumentMatchers.anyInt;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioRecordUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioRecordUnitTest.java
index 9c813c2..71228e2 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioRecordUnitTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioRecordUnitTest.java
@@ -16,10 +16,10 @@
 
 package com.android.mediaframeworktest.unit;
 
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
 import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
 
 import static org.junit.Assert.assertEquals;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioTrackUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioTrackUnitTest.java
index ffed39a..ac24a10 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioTrackUnitTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/AudioTrackUnitTest.java
@@ -16,10 +16,10 @@
 
 package com.android.mediaframeworktest.unit;
 
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
+import static android.content.Context.DEVICE_ID_DEFAULT;
 import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE;
 
 import static org.junit.Assert.assertEquals;
diff --git a/packages/AppPredictionLib/Android.bp b/packages/AppPredictionLib/Android.bp
index 5a68fdc..31c1936 100644
--- a/packages/AppPredictionLib/Android.bp
+++ b/packages/AppPredictionLib/Android.bp
@@ -25,7 +25,7 @@
     name: "app_prediction",
 
     sdk_version: "system_current",
-    min_sdk_version: "system_current",
+    min_sdk_version: "current",
 
     srcs: [
         "src/**/*.java",
diff --git a/packages/CarrierDefaultApp/res/values-af/strings.xml b/packages/CarrierDefaultApp/res/values-af/strings.xml
index 13ae4da..cb911d8 100644
--- a/packages/CarrierDefaultApp/res/values-af/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-af/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Byvoorbeeld, die aanmeldbladsy behoort dalk nie aan die organisasie wat gewys word nie."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Gaan in elk geval deur blaaier voort"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestasiehupstoot"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Verbeter jou 5G-ervaring"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s beveel aan dat jy ’n werkverrigtinghupstootpakket koop. Tik om deur %2$s te koop."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nie nou nie"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Bestuur"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Koop ’n prestasiehupstoot."</string>
diff --git a/packages/CarrierDefaultApp/res/values-am/strings.xml b/packages/CarrierDefaultApp/res/values-am/strings.xml
index e1f91ce..edaa248 100644
--- a/packages/CarrierDefaultApp/res/values-am/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-am/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ለምሳሌ፣ የመግቢያ ገጹ የሚታየው ድርጅት ላይሆን ይችላል።"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ለማንኛውም በአሳሽ በኩል ይቀጥሉ"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"የአፈጻጸም ጭማሪ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"የእርስዎን የ5ጂ ተሞክሮ ያሻሽሉ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s የአፈጻጸም መጨመሪያ ዕቅድ መግዛትን ይመክራል። በ%2$s ለመግዛት መታ ያድርጉ።"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"አሁን አይደለም"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"አስተዳድር"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"የአፈጻጸም ጭማሪ ይግዙ።"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ar/strings.xml b/packages/CarrierDefaultApp/res/values-ar/strings.xml
index c2e5ba8..9bc5e45 100644
--- a/packages/CarrierDefaultApp/res/values-ar/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ar/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"على سبيل المثال، قد لا تنتمي صفحة تسجيل الدخول إلى المؤسسة المعروضة."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"المتابعة على أي حال عبر المتصفح"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"تطبيق تعزيز الأداء"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"تحسين تجربة شبكة الجيل الخامس"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏هناك اقتراح من ‏\"%1$s\" لشراء خطة لتعزيز الأداء. انقر للشراء من خلال ‏\"%2$s\"."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"لاحقًا"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"إدارة"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"شراء تطبيق تعزيز الأداء"</string>
diff --git a/packages/CarrierDefaultApp/res/values-as/strings.xml b/packages/CarrierDefaultApp/res/values-as/strings.xml
index 8881940..732c52d 100644
--- a/packages/CarrierDefaultApp/res/values-as/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-as/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"উদাহৰণস্বৰূপে, আপোনাক দেখুওৱা লগ ইনৰ পৃষ্ঠাটো প্ৰতিষ্ঠানটোৰ নিজা নহ\'বও পাৰে।"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"তথাপিও ব্ৰাউজাৰৰ জৰিয়তে অব্যাহত ৰাখক"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"কাৰ্যক্ষমতা পৰিৱৰ্ধন"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"আপোনাৰ 5G অভিজ্ঞতা উন্নত কৰক"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$sএ এখন কাৰ্যক্ষমতা পৰিৱৰ্ধন অঁচনি ক্ৰয় কৰাৰ চুপাৰিছ কৰে। %2$sৰ জৰিয়তে ক্ৰয় কৰিবলৈ টিপক।"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"এতিয়া নহয়"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"পৰিচালনা কৰক"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"এটা কাৰ্যক্ষমতা পৰিৱৰ্ধন ক্ৰয় কৰক।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-az/strings.xml b/packages/CarrierDefaultApp/res/values-az/strings.xml
index f64fcb6..05c300f 100644
--- a/packages/CarrierDefaultApp/res/values-az/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-az/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Məsələn, giriş səhifəsi göstərilən təşkilata aid olmaya bilər."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Hər bir halda brazuer ilə davam edin"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performans artırması"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G təcrübənizi təkmilləşdirin"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s performans artırma planı almağı tövsiyə edir. %2$s ilə almaq üçün toxunun."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"İndi yox"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"İdarə edin"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Performans artırması alın."</string>
diff --git a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
index 5533bfd..deeb5c7 100644
--- a/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-b+sr+Latn/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Na primer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko pregledača"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Poboljšanje učinka"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte 5G doživljaj"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupovinu paketa za poboljšanje performansi. Dodirnite da biste kupili preko %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sada"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljaj"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite poboljšanje učinka."</string>
diff --git a/packages/CarrierDefaultApp/res/values-be/strings.xml b/packages/CarrierDefaultApp/res/values-be/strings.xml
index 0053cda..4f820ca 100644
--- a/packages/CarrierDefaultApp/res/values-be/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-be/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Напрыклад, старонка ўваходу можа не належаць указанай арганізацыі."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Усё роўна працягнуць праз браўзер"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Павышэнне прадукцыйнасці"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Пашырце магчымасці 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s рэкамендуе купіць план павышэння прадукцыйнасці. Націсніце, каб купіць праз %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не цяпер"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Кіраваць"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Аплаціце павышэнне прадукцыйнасці."</string>
diff --git a/packages/CarrierDefaultApp/res/values-bg/strings.xml b/packages/CarrierDefaultApp/res/values-bg/strings.xml
index a37e0a3..a32c632 100644
--- a/packages/CarrierDefaultApp/res/values-bg/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bg/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Например страницата за вход може да не принадлежи на показаната организация."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Продължаване през браузър въпреки това"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Увеличаване на ефективността"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Подобряване на практическата работа с 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препоръчва да купите план за увеличаване на ефективността. Докоснете, за да купите чрез %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сега"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управление"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Купете пакет за увеличаване на ефективността."</string>
diff --git a/packages/CarrierDefaultApp/res/values-bn/strings.xml b/packages/CarrierDefaultApp/res/values-bn/strings.xml
index f78449c..ac4fab4 100644
--- a/packages/CarrierDefaultApp/res/values-bn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bn/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"যেমন, লগ-ইন পৃষ্ঠাটি যে প্রতিষ্ঠানের পৃষ্ঠা বলে দেখানো আছে, আসলে তা নাও হতে পারে৷"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"যাই হোক, ব্রাউজারের মাধ্যমে চালিয়ে যান"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"পারফর্ম্যান্স বুস্ট"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"আপনার 5G অভিজ্ঞতা উন্নত করুন"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s পারফর্ম্যান্স বুস্ট প্ল্যান কেনার সাজেশন দেয়। %2$s-এর মাধ্যমে কিনতে ট্যাপ করুন।"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"এখন নয়"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ম্যানেজ করুন"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"পারফর্ম্যান্স বুস্ট সংক্রান্ত ফিচার কিনুন।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-bs/strings.xml b/packages/CarrierDefaultApp/res/values-bs/strings.xml
index 7be8e2b..cc59f9db 100644
--- a/packages/CarrierDefaultApp/res/values-bs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-bs/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Naprimjer, stranica za prijavljivanje možda ne pripada prikazanoj organizaciji."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi preko preglednika"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Pojačavanje performansi"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte iskustvo s 5G mrežom"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupovinu paketa za poboljšanje performansi. Dodirnite da kupite koristeći %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sada"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljajte"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite pojačavanje performansi."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ca/strings.xml b/packages/CarrierDefaultApp/res/values-ca/strings.xml
index 54c9e6e..ded2263 100644
--- a/packages/CarrierDefaultApp/res/values-ca/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ca/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Per exemple, la pàgina d\'inici de sessió podria no pertànyer a l\'organització que es mostra."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continua igualment mitjançant el navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimització de rendiment"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Millora l\'experiència 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomana comprar un pla d\'optimització de rendiment. Toca per comprar-lo mitjançant %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ara no"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestiona"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra una optimització de rendiment."</string>
diff --git a/packages/CarrierDefaultApp/res/values-cs/strings.xml b/packages/CarrierDefaultApp/res/values-cs/strings.xml
index 8a09421..d21c500 100644
--- a/packages/CarrierDefaultApp/res/values-cs/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-cs/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Přihlašovací stránka například nemusí patřit zobrazované organizaci."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Přesto pokračovat prostřednictvím prohlížeče"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zvýšení výkonu"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Získejte rychlejší připojení 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s doporučuje zakoupit zvýšení výkonu. Klepnutím ho zakoupíte přes operátora %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Teď ne"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Spravovat"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupte si zvýšení výkonu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-da/strings.xml b/packages/CarrierDefaultApp/res/values-da/strings.xml
index cd411c9..192036d 100644
--- a/packages/CarrierDefaultApp/res/values-da/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-da/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Det er f.eks. ikke sikkert, at loginsiden tilhører den anførte organisation."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Fortsæt alligevel via browseren"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ydeevneboost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Få en bedre 5G-oplevelse"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anbefaler, at du køber et abonnement med ydeevneboost. Tryk for at købe via %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ikke nu"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrer"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Køb et ydeevneboost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-de/strings.xml b/packages/CarrierDefaultApp/res/values-de/strings.xml
index d20a1e8..0226d9f 100644
--- a/packages/CarrierDefaultApp/res/values-de/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-de/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Beispiel: Die Log-in-Seite gehört eventuell nicht zur angezeigten Organisation."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Trotzdem in einem Browser fortfahren"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Leistungs-Boost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G-Nutzung verbessern"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s empfiehlt den Kauf eines Tarifs mit Leistungs-Boost. Du kannst tippen, um über %2$s einen zu kaufen."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nicht jetzt"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Verwalten"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Leistungs-Boost erwerben."</string>
diff --git a/packages/CarrierDefaultApp/res/values-el/strings.xml b/packages/CarrierDefaultApp/res/values-el/strings.xml
index 0759011..96e3eb3 100644
--- a/packages/CarrierDefaultApp/res/values-el/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-el/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Για παράδειγμα, η σελίδα σύνδεσης ενδέχεται να μην ανήκει στον οργανισμό που εμφανίζεται."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Συνέχεια ούτως ή άλλως μέσω του προγράμματος περιήγησης"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ενίσχυση απόδοσης"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Βελτιώστε την εμπειρία 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"Το %1$s προτείνει την αγορά ενός προγράμματος ενίσχυσης απόδοσης. Πατήστε για αγορά μέσω %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Όχι τώρα"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Διαχείριση"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Αγοράστε μια ενίσχυση απόδοσης."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml b/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
index 720dbc7..aac44fc 100644
--- a/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rAU/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml b/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
index 87978ac..d8ec210 100644
--- a/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rCA/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page may not belong to the organization shown."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"Improve your app experience"</string>
+    <string name="performance_boost_notification_detail" msgid="86969987181456032">"Tap to visit %s\'s website and learn more."</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml b/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
index 720dbc7..aac44fc 100644
--- a/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rGB/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml b/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
index 720dbc7..aac44fc 100644
--- a/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rIN/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"For example, the login page might not belong to the organisation shown."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continue anyway via browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performance boost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Improve your 5G experience"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommends buying a performance boost plan. Tap to buy through %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Not now"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Manage"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Purchase a performance boost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml b/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
index 7324a5b..87b007f 100644
--- a/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-en-rXC/strings.xml
@@ -15,8 +15,8 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎For example, the login page may not belong to the organization shown.‎‏‎‎‏‎"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎Continue anyway via browser‎‏‎‎‏‎"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‎‎‎‎‎‎Performance boost‎‏‎‎‏‎"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‎‏‎‎‎‏‎‎‎‎Improve your 5G experience‎‏‎‎‏‎"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‏‏‎%1$s recommends buying a performance boost plan. Tap to buy through %2$s.‎‏‎‎‏‎"</string>
+    <string name="performance_boost_notification_title" msgid="6091638924925876776">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎Improve your app experience‎‏‎‎‏‎"</string>
+    <string name="performance_boost_notification_detail" msgid="86969987181456032">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‎‎‎‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‎Tap to visit %s\'s website and learn more.‎‏‎‎‏‎"</string>
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎Not now‎‏‎‎‏‎"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‎‏‎‏‎Manage‎‏‎‎‏‎"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎Purchase a performance boost.‎‏‎‎‏‎"</string>
diff --git a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
index fedf1ac..1ad7751 100644
--- a/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-es-rUS/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por ejemplo, es posible que la página de acceso no pertenezca a la organización que aparece."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar de todos modos desde el navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de rendimiento"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Mejora tu experiencia de 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomienda que compres un plan de aumento de rendimiento. Presiona para comprar mediante %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ahora no"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrar"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Compra un aumento de rendimiento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-es/strings.xml b/packages/CarrierDefaultApp/res/values-es/strings.xml
index 85642b8..972afa9 100644
--- a/packages/CarrierDefaultApp/res/values-es/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-es/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por ejemplo, es posible que la página de inicio de sesión no pertenezca a la organización mostrada."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar de todos modos a través del navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Mejora de rendimiento"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Mejora tu experiencia 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomienda comprar un plan de mejora del rendimiento. Toca para comprarlo mediante %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ahora no"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestionar"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar una mejora de rendimiento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-et/strings.xml b/packages/CarrierDefaultApp/res/values-et/strings.xml
index 769f240..1ac991c 100644
--- a/packages/CarrierDefaultApp/res/values-et/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-et/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Näiteks ei pruugi sisselogimisleht kuuluda kuvatavale organisatsioonile."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Jätka siiski brauseris"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Jõudluse võimendus"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Täiustage oma 5G-kogemust"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s soovitab osta jõudluse võimendusega paketi. Puudutage teenuse %2$s kaudu ostmiseks."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Mitte praegu"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Haldamine"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Ostke jõudluse võimendus."</string>
diff --git a/packages/CarrierDefaultApp/res/values-eu/strings.xml b/packages/CarrierDefaultApp/res/values-eu/strings.xml
index 7274bce..fedf29d 100644
--- a/packages/CarrierDefaultApp/res/values-eu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-eu/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Adibidez, baliteke saioa hasteko orria adierazitako erakundearena ez izatea."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Jarraitu arakatzailearen bidez, halere"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Errendimendu-hobekuntza"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Hobetu 5G bidezko konexioa"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s zerbitzuak errendimendua hobetzeko kidetza bat erostea gomendatzen du. Sakatu hau %2$s bidez erosteko."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Orain ez"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kudeatu"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Erosi errendimendu-hobekuntza bat."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fa/strings.xml b/packages/CarrierDefaultApp/res/values-fa/strings.xml
index 2cbe297..a9ac157 100644
--- a/packages/CarrierDefaultApp/res/values-fa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fa/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"به عنوان مثال، صفحه ورود به سیستم ممکن است متعلق به سازمان نشان داده شده نباشد."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"درهر صورت ازطریق مرورگر ادامه یابد"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"تقویت‌کننده عملکرد"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"تجربه نسل پنجم شبکه تلفن همراه را بهبود دهید"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏%1$s توصیه می‌کند طرح تقویت عملکرد خریداری شود. برای خرید ازطریق %2$s، ضربه بزنید."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"اکنون نه"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"مدیریت"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"تقویت‌کننده عملکرد خریداری کنید."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fi/strings.xml b/packages/CarrierDefaultApp/res/values-fi/strings.xml
index 1a388cd..e0bf1e7 100644
--- a/packages/CarrierDefaultApp/res/values-fi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fi/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Kirjautumissivu ei välttämättä kuulu näytetylle organisaatiolle."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Jatka selaimen kautta"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Suorituskykyboosti"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Paranna 5G-kokemusta"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s suosittelee suorituskykyboostipaketin ostamista. Napauta ja tee ostos operaattorilla %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ei nyt"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Muuta"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Osta suorituskykyboosti."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml b/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
index ad6c794..a56a4db 100644
--- a/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fr-rCA/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Par exemple, la page de connexion pourrait ne pas appartenir à l\'organisation représentée."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuer quand même dans un navigateur"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Optimiseur de performances"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Améliorer votre expérience de la 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommande d\'acheter un forfait d\'amélioration des performances. Touchez pour acheter par l\'intermédiaire de %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Plus tard"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gérer"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez un optimiseur de performances."</string>
diff --git a/packages/CarrierDefaultApp/res/values-fr/strings.xml b/packages/CarrierDefaultApp/res/values-fr/strings.xml
index 92b47be..699d4b3 100644
--- a/packages/CarrierDefaultApp/res/values-fr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fr/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Par exemple, la page de connexion peut ne pas appartenir à l\'organisation représentée."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuer quand même dans le navigateur"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Boost de performances"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Améliorer votre expérience 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recommande d\'acheter un forfait d\'amélioration des performances. Appuyez pour acheter via %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Pas maintenant"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gérer"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Achetez un boost de performances."</string>
diff --git a/packages/CarrierDefaultApp/res/values-gl/strings.xml b/packages/CarrierDefaultApp/res/values-gl/strings.xml
index 2c1be52..b252b8c 100644
--- a/packages/CarrierDefaultApp/res/values-gl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gl/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, é posible que a páxina de inicio de sesión non pertenza á organización que se mostra."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar igualmente co navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Mellora de rendemento"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Mellora a túa experiencia 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda comprar un plan de mellora do rendemento. Toca para realizar a compra a través de %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora non"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Xestionar"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar unha mellora de rendemento."</string>
diff --git a/packages/CarrierDefaultApp/res/values-gu/strings.xml b/packages/CarrierDefaultApp/res/values-gu/strings.xml
index af09d13..8f1174a 100644
--- a/packages/CarrierDefaultApp/res/values-gu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-gu/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ઉદાહરણ તરીકે, લોગિન પૃષ્ઠ બતાવવામાં આવેલી સંસ્થાનું ન પણ હોય."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"તો પણ બ્રાઉઝર મારફતે ચાલુ રાખો"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"પર્ફોર્મન્સ બૂસ્ટ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"તમારા 5G અનુભવને બહેતર બનાવો"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s પર્ફોર્મન્સ બૂસ્ટ પ્લાન ખરીદવાનો સુઝાવ આપે છે. %2$s મારફતે ખરીદવા માટે ટૅપ કરો."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"હમણાં નહીં"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"મેનેજ કરો"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"પર્ફોર્મન્સ બૂસ્ટ ખરીદો."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hi/strings.xml b/packages/CarrierDefaultApp/res/values-hi/strings.xml
index e51b1a9..52da322 100644
--- a/packages/CarrierDefaultApp/res/values-hi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hi/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"उदाहरण के लिए, हो सकता है कि लॉगिन पेज दिखाए गए संगठन का ना हो."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ब्राउज़र के ज़रिए किसी भी तरह जारी रखें"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफ़ॉर्मेंस बूस्ट"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G का बेहतर अनुभव पाएं"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s, परफ़ॉर्मेंस को बेहतर बनाने वाले प्लान को खरीदने का सुझाव देता है. %2$s से प्लान खरीदने के लिए टैप करें."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"अभी नहीं"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"मैनेज करें"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"कोई परफ़ॉर्मेंस बूस्ट खरीदें."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hr/strings.xml b/packages/CarrierDefaultApp/res/values-hr/strings.xml
index 5a22ad5..1b60123 100644
--- a/packages/CarrierDefaultApp/res/values-hr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hr/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Na primjer, stranica za prijavu možda ne pripada prikazanoj organizaciji."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Ipak nastavi putem preglednika"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Poboljšanje izvedbe"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Poboljšajte svoj 5G doživljaj"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s preporučuje kupnju paketa za poboljšanje izvedbe. Dodirnite da biste kupili putem usluge %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne sad"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljajte"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite poboljšanje izvedbe."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hu/strings.xml b/packages/CarrierDefaultApp/res/values-hu/strings.xml
index a841cb2..026586b 100644
--- a/packages/CarrierDefaultApp/res/values-hu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hu/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Például lehetséges, hogy a bejelentkezési oldal nem a megjelenített szervezethez tartozik."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Folytatás ennek ellenére böngészőn keresztül"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Teljesítménynövelés"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Az 5G-élmény javítása"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"A(z) %1$s teljesítménynövelő csomag vásárlását javasolja. Koppintson a(z) %2$s szolgáltatón keresztüli vásárláshoz."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Most nem"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kezelés"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Vásároljon teljesítménynövelést."</string>
diff --git a/packages/CarrierDefaultApp/res/values-hy/strings.xml b/packages/CarrierDefaultApp/res/values-hy/strings.xml
index 49fbece..dc93d6e 100644
--- a/packages/CarrierDefaultApp/res/values-hy/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-hy/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Օրինակ՝ մուտքի էջը կարող է ցուցադրված կազմակերպության էջը չլինել:"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Շարունակել դիտարկիչի միջոցով"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Արտադրողականության բարձրացում"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Բարելավեք 5G-ի օգտագործման ձեր փորձառությունը"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s օպերատորը խորհուրդ է տալիս ձեռք բերել արդյունավետությունը բարձրացնող սակագնային պլան։ Հպեք՝ %2$s-ի միջոցով գնելու համար։"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ոչ հիմա"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Կառավարել"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Բարձրացրեք ցանցի արտադրողականությունը վճարի դիմաց։"</string>
diff --git a/packages/CarrierDefaultApp/res/values-in/strings.xml b/packages/CarrierDefaultApp/res/values-in/strings.xml
index 170bd76..56b8b2e 100644
--- a/packages/CarrierDefaultApp/res/values-in/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-in/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Misalnya, halaman login mungkin bukan milik organisasi yang ditampilkan."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Tetap lanjutkan melalui browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Penguat sinyal"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Tingkatkan pengalaman 5G Anda"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s merekomendasikan pembelian paket penguat sinyal. Ketuk untuk membeli melalui %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Lain kali"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Kelola"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Beli penguat sinyal."</string>
diff --git a/packages/CarrierDefaultApp/res/values-is/strings.xml b/packages/CarrierDefaultApp/res/values-is/strings.xml
index 8684ee6..510d5fd 100644
--- a/packages/CarrierDefaultApp/res/values-is/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-is/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Til dæmis getur verið að innskráningarsíðan tilheyri ekki fyrirtækinu sem birtist."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Halda samt áfram í vafra"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Afkastaaukning"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Bættu upplifun þína af 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s mælir með að kaupa áskrift sem eykur afköst. Ýttu til að kaupa í gegnum %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ekki núna"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Stjórna"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kaupa afkastaaukningu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-it/strings.xml b/packages/CarrierDefaultApp/res/values-it/strings.xml
index ea88457..324aa4f 100644
--- a/packages/CarrierDefaultApp/res/values-it/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-it/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Ad esempio, la pagina di accesso potrebbe non appartenere all\'organizzazione indicata."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continua comunque dal browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento di prestazioni"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Migliora la tua esperienza 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s consiglia l\'acquisto di un piano di miglioramento delle prestazioni. Tocca per acquistare tramite %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Non ora"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestisci"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Acquista un aumento di prestazioni."</string>
diff --git a/packages/CarrierDefaultApp/res/values-iw/strings.xml b/packages/CarrierDefaultApp/res/values-iw/strings.xml
index c7229ba..9e2f31c 100644
--- a/packages/CarrierDefaultApp/res/values-iw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-iw/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"לדוגמה, ייתכן שדף ההתחברות אינו שייך לארגון המוצג."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"המשך בכל זאת באמצעות דפדפן"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"שיפור ביצועים"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"‏שיפור חווית השימוש ב-5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏יש המלצה של %1$s לקנות תוכנית לשיפור הביצועים. אפשר להקיש כדי לקנות דרך %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"לא עכשיו"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ניהול"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"רכישת שיפור ביצועים."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ja/strings.xml b/packages/CarrierDefaultApp/res/values-ja/strings.xml
index 2fd86c8..833f8a5 100644
--- a/packages/CarrierDefaultApp/res/values-ja/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ja/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"たとえば、ログインページが表示されている組織に属していない可能性があります。"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ブラウザから続行"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"パフォーマンス ブースト"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G のエクスペリエンスを改善"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s さんがパフォーマンス ブースト プランの購入をおすすめしています。%2$sまでにタップして購入しましょう。"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"後で"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"パフォーマンス ブーストを購入してください。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ka/strings.xml b/packages/CarrierDefaultApp/res/values-ka/strings.xml
index 76f7273..507e0d9 100644
--- a/packages/CarrierDefaultApp/res/values-ka/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ka/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"მაგალითად, სისტემაში შესვლის გვერდი შეიძლება არ ეკუთვნოდეს ნაჩვენებ ორგანიზაციას."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"მაინც ბრაუზერში გაგრძელება"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ეფექტურობის გაძლიერება"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"გააუმჯობესეთ თქვენი 5G გამოცდილება"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s-ის მიერ რეკომენდებულია ეფექტურობის გაძლიერების გეგმის შეძენა. შეეხეთ %2$s-ის დახმარებით შესაძენად."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ახლა არა"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"მართვა"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ეფექტურობის გაძლიერების შეძენა."</string>
diff --git a/packages/CarrierDefaultApp/res/values-kk/strings.xml b/packages/CarrierDefaultApp/res/values-kk/strings.xml
index 4a895f4..32eae44 100644
--- a/packages/CarrierDefaultApp/res/values-kk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kk/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Мысалы, кіру беті көрсетілген ұйымға тиесілі болмауы мүмкін."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Бәрібір браузер арқылы жалғастыру"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Өнімділікті арттыру"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G желісімен жұмысыңызды жақсартыңыз"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s өнімділікті арттыру жоспарын сатып алуды ұсынады. %2$s операторынан сатып алу үшін түртіңіз."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Қазір емес"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Басқару"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Өнімділікті арттыру құралын сатып алыңыз."</string>
diff --git a/packages/CarrierDefaultApp/res/values-km/strings.xml b/packages/CarrierDefaultApp/res/values-km/strings.xml
index 51a51ff..531226f 100644
--- a/packages/CarrierDefaultApp/res/values-km/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-km/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ឧទាហរណ៍៖ ទំព័រចូលនេះអាចនឹងមិនមែនជាកម្មសិទ្ធិរបស់ស្ថាប័នដែលបានបង្ហាញនេះទេ។"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"យ៉ាងណាក៏ដោយនៅតែបន្តតាមរយៈកម្មវិធីរុករកតាមអ៊ីនធឺណិត"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ការបង្កើនប្រតិបត្តិការ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"កែលម្អបទពិសោធន៍ប្រើ 5G របស់អ្នក"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ណែនាំឱ្យទិញផែនការជំរុញប្រតិបត្តិការ។ ចុចដើម្បីទិញតាមរយៈ %2$s។"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"កុំទាន់"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"គ្រប់គ្រង"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ទិញការបង្កើនប្រតិបត្តិការ។"</string>
diff --git a/packages/CarrierDefaultApp/res/values-kn/strings.xml b/packages/CarrierDefaultApp/res/values-kn/strings.xml
index c97d6f0..4335d0c 100644
--- a/packages/CarrierDefaultApp/res/values-kn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kn/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ಉದಾಹರಣೆಗೆ, ಲಾಗಿನ್ ಪುಟವು ತೋರಿಸಲಾಗಿರುವ ಸಂಸ್ಥೆಗೆ ಸಂಬಂಧಿಸಿಲ್ಲದಿರಬಹುದು."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ಪರವಾಗಿಲ್ಲ, ಬ್ರೌಸರ್ ಮೂಲಕ ಮುಂದುವರಿಸಿ"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ನಿಮ್ಮ 5G ಅನುಭವವನ್ನು ಸುಧಾರಿಸಿ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"ಕಾರ್ಯಕ್ಷಮತೆಯನ್ನು ಹೆಚ್ಚಿಸುವ ಪ್ಲಾನ್ ಅನ್ನು ಖರೀದಿಸಲು %1$s ಶಿಫಾರಸು ಮಾಡುತ್ತದೆ. %2$s ಮೂಲಕ ಖರೀದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ಈಗ ಬೇಡ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ನಿರ್ವಹಿಸಿ"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ಕಾರ್ಯಕ್ಷಮತೆ ಬೂಸ್ಟ್ ಅನ್ನು ಖರೀದಿಸಿ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ko/strings.xml b/packages/CarrierDefaultApp/res/values-ko/strings.xml
index 395627d..3bb5628 100644
--- a/packages/CarrierDefaultApp/res/values-ko/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ko/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"예를 들어 로그인 페이지가 표시된 조직에 속하지 않을 수 있습니다."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"브라우저를 통해 계속하기"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"성능 향상"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G 사용 환경 개선"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s에서 성능 향상 계획 구매를 추천합니다. %2$s을(를) 통해 구매하려면 탭하세요."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"나중에"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"관리"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"성능 향상 구매"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ky/strings.xml b/packages/CarrierDefaultApp/res/values-ky/strings.xml
index b3970e3..07bb618 100644
--- a/packages/CarrierDefaultApp/res/values-ky/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ky/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Мисалы, аккаунтка кирүү баракчасы көрсөтүлгөн уюмга таандык эмес болушу мүмкүн."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Баары бир серепчи аркылуу улантуу"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Иштин майнаптуулугун жогорулатуу"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G менен оңой иштеңиз"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s майнаптуулугун жогорулата турган тарифтик планды сатып алууну сунуштайт. %2$s аркылуу сатып алуу үчүн таптаңыз."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Азыр эмес"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Тескөө"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Иштин майнаптуулугун жогорулатууну сатып алыңыз."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lo/strings.xml b/packages/CarrierDefaultApp/res/values-lo/strings.xml
index 70d8888..480a7ce 100644
--- a/packages/CarrierDefaultApp/res/values-lo/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lo/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ຕົວຢ່າງ, ໜ້າເຂົ້າສູ່ລະບົບອາດຈະບໍ່ແມ່ນຂອງອົງກອນທີ່ປາກົດ."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ດຳເນີນການຕໍ່ຜ່ານໂປຣແກຣມທ່ອງເວັບ"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ເລັ່ງປະສິດທິພາບ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ປັບປຸງປະສົບການ 5G ຂອງທ່ານ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ແນະນຳໃຫ້ຊື້ແຜນການເລັ່ງປະສິດທິພາບ. ແຕະເພື່ອຊື້ຜ່ານ %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ບໍ່ຟ້າວເທື່ອ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ຈັດການ"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ຊື້ການເລັ່ງປະສິດທິພາບ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lt/strings.xml b/packages/CarrierDefaultApp/res/values-lt/strings.xml
index 8068416..1f4a433 100644
--- a/packages/CarrierDefaultApp/res/values-lt/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lt/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Pavyzdžiui, prisijungimo puslapis gali nepriklausyti rodomai organizacijai."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Vis tiek tęsti naudojant naršyklę"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Našumo pagerinimas"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Pagerinkite 5G ryšį"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"„%1$s“ rekomenduoja įsigyti našumo pagerinimo planą. Palieskite, kad įsigytumėte naudodamiesi „%2$s“ paslaugomis."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne dabar"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Tvarkyti"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Įsigykite našumo pagerinimo paslaugą."</string>
diff --git a/packages/CarrierDefaultApp/res/values-lv/strings.xml b/packages/CarrierDefaultApp/res/values-lv/strings.xml
index 1fefe92..2fd9837 100644
--- a/packages/CarrierDefaultApp/res/values-lv/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-lv/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Piemēram, pieteikšanās lapa, iespējams, nepieder norādītajai organizācijai."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Tomēr turpināt, izmantojot pārlūkprogrammu"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Veiktspējas uzlabojums"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Uzlabojiet 5G iespējas"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s iesaka iegādāties veiktspējas uzlabošanas plānu. Pieskarieties, lai to iegādātos no %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Vēlāk"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Pārvaldīt"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Iegādājieties veiktspējas uzlabojumu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mk/strings.xml b/packages/CarrierDefaultApp/res/values-mk/strings.xml
index 425edfc..6eca2b5 100644
--- a/packages/CarrierDefaultApp/res/values-mk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mk/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"На пример, страницата за најавување може да не припаѓа на прикажаната организација."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Сепак продолжи преку прелистувач"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Засилување на изведбата"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Подобрете го вашето доживување со 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препорачува да купите пакет за засилување на изведбата. Допрете за да купите преку %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сега"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управувајте"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Купете засилување на изведбата."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ml/strings.xml b/packages/CarrierDefaultApp/res/values-ml/strings.xml
index f258411..2577a144 100644
--- a/packages/CarrierDefaultApp/res/values-ml/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ml/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ഉദാഹരണത്തിന്, കാണിച്ചിരിക്കുന്ന ഓർഗനൈസേഷന്റേതായിരിക്കില്ല ലോഗിൻ പേജ്."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"എന്തായാലും ബ്രൗസർ വഴി തുടരുക"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"പ്രകടന ബൂസ്റ്റ്"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"നിങ്ങളുടെ 5G അനുഭവം മെച്ചപ്പെടുത്തുക"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"പ്രകടന ബൂസ്റ്റ് പ്ലാൻ വാങ്ങാൻ %1$s നിർദ്ദേശിക്കുന്നു. %2$s വഴി വാങ്ങാൻ ടാപ്പ് ചെയ്യുക."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ഇപ്പോൾ വേണ്ട"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"മാനേജ് ചെയ്യുക"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"പ്രകടന ബൂസ്റ്റ് വാങ്ങൂ."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mn/strings.xml b/packages/CarrierDefaultApp/res/values-mn/strings.xml
index 12e1719..f0fc546 100644
--- a/packages/CarrierDefaultApp/res/values-mn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mn/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Жишээлбэл нэвтрэх хуудас нь харагдаж буй байгууллагынх биш байж болно."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Ямар ч тохиолдолд хөтчөөр үргэлжлүүлэх"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Гүйцэтгэлийн идэвхжүүлэлт"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G-н хэрэглээгээ сайжруулах"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s гүйцэтгэл нэмэгдүүлэх багцыг худалдаж авахыг зөвлөж байна. %2$s-р дамжуулан худалдан авах бол товшино уу."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Одоо биш"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Удирдах"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Гүйцэтгэлийн идэвхжүүлэлтийг худалдаж аваарай."</string>
diff --git a/packages/CarrierDefaultApp/res/values-mr/strings.xml b/packages/CarrierDefaultApp/res/values-mr/strings.xml
index a48c605..75cbb1b 100644
--- a/packages/CarrierDefaultApp/res/values-mr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-mr/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणार्थ, लॉग इन पृष्‍ठ दर्शवलेल्या संस्थेच्या मालकीचे नसू शकते."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"तरीही ब्राउझरद्वारे सुरू ठेवा"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"परफॉर्मन्स बूस्ट"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"तुमच्या 5G अनुभवामध्ये सुधारणा करा"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s हे परफॉर्मन्स बूस्ट प्लॅन खरेदी करण्याची शिफारस करते. %2$s वरून खरेदी करण्यासाठी टॅप करा."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"आता नको"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"व्यवस्थापित करा"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"परफॉर्मन्स बूस्ट खरेदी करा."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ms/strings.xml b/packages/CarrierDefaultApp/res/values-ms/strings.xml
index 85651f4..1484233 100644
--- a/packages/CarrierDefaultApp/res/values-ms/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ms/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Contohnya, halaman log masuk mungkin bukan milik organisasi yang ditunjukkan."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Teruskan juga melalui penyemak imbas"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Peningkatan prestasi"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Tingkatkan pengalaman 5G anda"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s mengesyorkan pembelian pelan peningkatan prestasi. Ketik untuk membeli melalui %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Bukan sekarang"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Urus"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Beli perangsang prestasi."</string>
diff --git a/packages/CarrierDefaultApp/res/values-my/strings.xml b/packages/CarrierDefaultApp/res/values-my/strings.xml
index 34c54b9..e7a860e 100644
--- a/packages/CarrierDefaultApp/res/values-my/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-my/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ဥပမာ− ဝင်ရောက်ရန် စာမျက်နှာသည် ပြသထားသည့် အဖွဲ့အစည်းနှင့် သက်ဆိုင်မှုမရှိခြင်း ဖြစ်နိုင်ပါသည်။"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"မည်သို့ပင်ဖြစ်စေ ဘရောက်ဇာမှတစ်ဆင့် ရှေ့ဆက်ရန်"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ်"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G အသုံးပြုမှု ပိုမိုကောင်းမွန်စေခြင်း"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s သည် စွမ်းဆောင်ရည်မြှင့်တင်သော အစီအစဉ်ဝယ်ရန် အကြံပြုပါသည်။ %2$s မှတစ်ဆင့် ဝယ်ရန် တို့ပါ။"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ယခုမလုပ်ပါ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"စီမံရန်"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"စွမ်းဆောင်ရည် မြှင့်တင်အက်ပ် ဝယ်ယူရန်။"</string>
diff --git a/packages/CarrierDefaultApp/res/values-nb/strings.xml b/packages/CarrierDefaultApp/res/values-nb/strings.xml
index b30e3d9..f0d0d7e 100644
--- a/packages/CarrierDefaultApp/res/values-nb/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nb/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Det er for eksempel mulig at påloggingssiden ikke tilhører organisasjonen som vises."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Fortsett likevel via nettleseren"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Bedre ytelse"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Få en bedre 5G-opplevelse"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anbefaler at du kjøper et abonnement for bedre ytelse. Trykk for å kjøpe via %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ikke nå"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Administrer"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kjøp bedre ytelse."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ne/strings.xml b/packages/CarrierDefaultApp/res/values-ne/strings.xml
index 4dccdb9..f2b0f6e 100644
--- a/packages/CarrierDefaultApp/res/values-ne/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ne/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"उदाहरणका लागि, लग इन पृष्ठ देखाइएको संस्थाको नहुन सक्छ।"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"जे भए पनि ब्राउजर मार्फत जारी राख्नुहोस्"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"पर्फर्मेन्स बुस्ट"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G प्रयोग गर्दा अझ राम्रो सुविधा पाउनुहोस्"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ले पर्फर्मेन्स बुस्ट योजना खरिद गर्न सिफारिस गर्छ। %2$s मार्फत खरिद गर्न ट्याप गर्नुहोस्।"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"अहिले होइन"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"व्यवस्थापन गर्नुहोस्"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"पर्फर्मेन्स बुस्ट किन्नुहोस्।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-nl/strings.xml b/packages/CarrierDefaultApp/res/values-nl/strings.xml
index 6a4642c..f8ff38a 100644
--- a/packages/CarrierDefaultApp/res/values-nl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-nl/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Zo hoort de weergegeven inlogpagina misschien niet bij de weergegeven organisatie."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Toch doorgaan via browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestatieboost"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Verbeter je 5G-functionaliteit"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s beveelt je aan een prestatieboostabonnement te kopen. Tik om er een te kopen via %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Niet nu"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Beheren"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Koop een prestatieboost."</string>
diff --git a/packages/CarrierDefaultApp/res/values-or/strings.xml b/packages/CarrierDefaultApp/res/values-or/strings.xml
index f7349f9..bbe6f25 100644
--- a/packages/CarrierDefaultApp/res/values-or/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-or/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ଉଦାହରଣସ୍ୱରୂପ, ଲଗଇନ୍‍ ପୃଷ୍ଠା ଦେଖାଯାଇଥିବା ସଂସ୍ଥାର ହୋଇନଥାଇପାରେ।"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ବ୍ରାଉଜର୍‍ ଜରିଆରେ ଯେମିତିବି ହେଉ ଜାରି ରଖନ୍ତୁ"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ପରଫରମାନ୍ସ ବୁଷ୍ଟ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ଆପଣଙ୍କ 5G ଅନୁଭୂତିକୁ ଉନ୍ନତ କରନ୍ତୁ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ ପ୍ଲାନ କିଣିବା ପାଇଁ ସୁପାରିଶ କରେ। %2$s ମାଧ୍ୟମରେ କିଣିବା ପାଇଁ ଟାପ କରନ୍ତୁ।"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ବର୍ତ୍ତମାନ ନୁହେଁ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ଏକ ପରଫରମାନ୍ସ ବୁଷ୍ଟ କିଣନ୍ତୁ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pa/strings.xml b/packages/CarrierDefaultApp/res/values-pa/strings.xml
index 540a54c..811eca9 100644
--- a/packages/CarrierDefaultApp/res/values-pa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pa/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ਉਦਾਹਰਣ ਵੱਜੋਂ, ਲੌਗ-ਇਨ ਪੰਨਾ ਦਿਖਾਈ ਗਈ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ।"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ਬ੍ਰਾਊਜ਼ਰ ਰਾਹੀਂ ਫਿਰ ਵੀ ਜਾਰੀ ਰੱਖੋ"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ਆਪਣਾ 5G ਅਨੁਭਵ ਬਿਹਤਰ ਬਣਾਓ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s ਵੱਲੋਂ ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਪਲਾਨ ਖਰੀਦਣ ਦੀ ਸਿਫ਼ਾਰਸ਼ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। %2$s ਰਾਹੀਂ ਖਰੀਦਣ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ਹੁਣੇ ਨਹੀਂ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ਕਾਰਗੁਜ਼ਾਰੀ ਬੂਸਟ ਖਰੀਦੋ।"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pl/strings.xml b/packages/CarrierDefaultApp/res/values-pl/strings.xml
index de957a9..3cd3297 100644
--- a/packages/CarrierDefaultApp/res/values-pl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pl/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Na przykład strona logowania może nie należeć do wyświetlanej organizacji."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Kontynuuj mimo to w przeglądarce"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zwiększenie wydajności"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Lepiej wykorzystaj potencjał 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"Operator %1$s zaleca zakup abonamentu o zwiększonej wydajności. Kliknij, aby kupić u operatora %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nie teraz"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Zarządzaj"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kup wzmocnienie wydajności"</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
index 4a144be..85f049d 100644
--- a/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt-rBR/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim pelo navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de performance"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore sua experiência 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda a compra de um plano para aumento de desempenho. Toque para comprar em %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerenciar"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar um aumento de performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
index 56e0c2d..981cc5f 100644
--- a/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt-rPT/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de início de sessão pode não pertencer à entidade apresentada."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim através do navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento do desempenho"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore a sua experiência 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda comprar um plano de melhoria do desempenho. Toque para comprar através do %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerir"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Compre um aumento do desempenho."</string>
diff --git a/packages/CarrierDefaultApp/res/values-pt/strings.xml b/packages/CarrierDefaultApp/res/values-pt/strings.xml
index 4a144be..85f049d 100644
--- a/packages/CarrierDefaultApp/res/values-pt/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-pt/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Por exemplo, a página de login pode não pertencer à organização mostrada."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuar mesmo assim pelo navegador"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Aumento de performance"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Melhore sua experiência 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomenda a compra de um plano para aumento de desempenho. Toque para comprar em %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Agora não"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gerenciar"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Comprar um aumento de performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ro/strings.xml b/packages/CarrierDefaultApp/res/values-ro/strings.xml
index f861137..287be5a 100644
--- a/packages/CarrierDefaultApp/res/values-ro/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ro/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"De exemplu, este posibil ca pagina de conectare să nu aparțină organizației afișate."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Continuă oricum prin browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Boost de performanță"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Îmbunătățește-ți experiența cu tehnologia 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s recomandă cumpărarea unui plan pentru îmbunătățirea performanței. Atinge pentru a cumpăra de la %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Nu acum"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Gestionează"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Achiziționează un boost de performanță."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ru/strings.xml b/packages/CarrierDefaultApp/res/values-ru/strings.xml
index f0bff17..fd1328a 100644
--- a/packages/CarrierDefaultApp/res/values-ru/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ru/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Например, страница входа в аккаунт может быть фиктивной."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Продолжить в браузере"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Повышение производительности"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Сделайте работу с 5G удобнее"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"\"%1$s\" рекомендует купить тарифный план, повышающий производительность. Чтобы приобрести тариф у оператора \"%2$s\", коснитесь экрана."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сейчас"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Настроить"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Повысьте производительность сети за плату."</string>
diff --git a/packages/CarrierDefaultApp/res/values-si/strings.xml b/packages/CarrierDefaultApp/res/values-si/strings.xml
index 166af5a..a1cd21d 100644
--- a/packages/CarrierDefaultApp/res/values-si/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-si/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"උදාහරණයක් ලෙස, පුරනය වන පිටුව පෙන්වා ඇති සංවිධානයට අයිති නැති විය හැක."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"කෙසේ වුවත් බ්‍රවුසරය හරහා ඉදිරියට යන්න"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"කාර්ය සාධනය ඉහළ නැංවීම"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ඔබේ 5G අත්දැකීම වැඩි දියුණු කරන්න"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s කාර්ය සාධනය වැඩි කිරීමේ සැලසුමක් මිල දී ගැනීම නිර්දේශ කරයි. %2$s හරහා මිල දී ගැනීමට තට්ටු කරන්න."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"දැන් නොවේ"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"කළමනාකරණය කරන්න"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"කාර්ය සාධනය ඉහළ නැංවීමක් මිල දී ගන්න."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sk/strings.xml b/packages/CarrierDefaultApp/res/values-sk/strings.xml
index a58bd06..2655065 100644
--- a/packages/CarrierDefaultApp/res/values-sk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sk/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Napríklad prihlasovacia stránka nemusí patriť uvedenej organizácii."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Pokračovať pomocou prehliadača"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Zvýšenie výkonu"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Zlepšite svoje prostredie 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s odporúča zakúpiť tarifu na zvýšenie výkonnosti. Klepnutím kúpte cez %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Teraz nie"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Spravovať"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kúpte si zvýšenie výkonu."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sl/strings.xml b/packages/CarrierDefaultApp/res/values-sl/strings.xml
index 3c1fd3e..32c2659 100644
--- a/packages/CarrierDefaultApp/res/values-sl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sl/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Stran za prijavo na primer morda ne pripada prikazani organizaciji."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Vseeno nadaljuj v brskalniku"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Ojačevalnik zmogljivosti"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Izboljšajte izkušnjo omrežja 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s priporoča nakup paketa ojačevalnika zmogljivosti. Dotaknite se za nakup prek »%2$s«."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Ne zdaj"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Upravljanje"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Kupite ojačevalnik zmogljivosti."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sq/strings.xml b/packages/CarrierDefaultApp/res/values-sq/strings.xml
index 618e335..f72af39 100644
--- a/packages/CarrierDefaultApp/res/values-sq/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sq/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"për shembull, faqja e identifikimit mund të mos i përkasë organizatës së shfaqur."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Vazhdo gjithsesi nëpërmjet shfletuesit"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Përforcimi i performancës"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Përmirëso përvojën tënde 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s rekomandon blerjen e një plani të përforcimit të performancës. Trokit për të blerë nëpërmjet %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Jo tani"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Menaxho"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Bli një paketë përforcimi të performancës."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sr/strings.xml b/packages/CarrierDefaultApp/res/values-sr/strings.xml
index d28bacc..466e38c 100644
--- a/packages/CarrierDefaultApp/res/values-sr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sr/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"На пример, страница за пријављивање можда не припада приказаној организацији."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Ипак настави преко прегледача"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Побољшање учинка"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Побољшајте 5G доживљај"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s препоручује куповину пакета за побољшање перформанси. Додирните да бисте купили преко %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не сада"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Управљај"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Купите побољшање учинка."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sv/strings.xml b/packages/CarrierDefaultApp/res/values-sv/strings.xml
index ac044ec..ff438b3 100644
--- a/packages/CarrierDefaultApp/res/values-sv/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sv/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Det kan t.ex. hända att inloggningssidan inte tillhör den organisation som visas."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Fortsätt ändå via webbläsaren"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Prestandahöjning"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Förbättra din 5G-upplevelse"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s rekommenderar att du köper en prenumeration som kan höja prestandan. Tryck för att köpa via %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Inte nu"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Hantera"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Köp en prestandahöjning."</string>
diff --git a/packages/CarrierDefaultApp/res/values-sw/strings.xml b/packages/CarrierDefaultApp/res/values-sw/strings.xml
index 1c72f30..17bcc0f 100644
--- a/packages/CarrierDefaultApp/res/values-sw/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-sw/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Kwa mfano, ukurasa wa kuingia katika akaunti unaweza usiwe unamilikiwa na shirika lililoonyeshwa."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Endelea hata hivyo kupitia kivinjari"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Kuongeza utendaji"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Boresha hali yako ya utumiaji wa 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s anapendekeza ununue mpango wa kuongeza utendaji. Gusa ili ununue kupitia %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Si sasa"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Dhibiti"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Nunua programu ya kuongeza utendaji."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ta/strings.xml b/packages/CarrierDefaultApp/res/values-ta/strings.xml
index cfc46e8..3c347e1 100644
--- a/packages/CarrierDefaultApp/res/values-ta/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ta/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"எடுத்துக்காட்டாக, உள்நுழைவுப் பக்கமானது காட்டப்படும் அமைப்பிற்குச் சொந்தமானதாக இல்லாமல் இருக்கலாம்."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"பரவாயில்லை, உலாவி வழியாகத் தொடர்க"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"பெர்ஃபார்மென்ஸ் பூஸ்ட்"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"உங்கள் 5G அனுபவத்தை மேம்படுத்துங்கள்"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"செயல்திறன் மேம்பாட்டுத் திட்டத்தை வாங்க %1$s பரிந்துரைக்கிறது. %2$s மூலம் வாங்க தட்டவும்."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"இப்போது வேண்டாம்"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"நிர்வகியுங்கள்"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ஒரு பெர்ஃபார்மென்ஸ் பூஸ்ட்டைப் பர்ச்சேஸ் செய்யுங்கள்."</string>
diff --git a/packages/CarrierDefaultApp/res/values-te/strings.xml b/packages/CarrierDefaultApp/res/values-te/strings.xml
index f31291e..003df39 100644
--- a/packages/CarrierDefaultApp/res/values-te/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-te/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ఉదాహరణకు, లాగిన్ పేజీ చూపిన సంస్థకు చెందినది కాకపోవచ్చు."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ఏదేమైనా బ్రౌజర్ ద్వారా కొనసాగించండి"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"పనితీరు బూస్ట్"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"మీ 5G అనుభవాన్ని మెరుగుపరుచుకోండి"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"పనితీరును బూస్ట్ చేసే ప్లాన్‌ను కొనుగోలు చేయమని %1$s సిఫార్సు చేస్తున్నారు. %2$s ద్వారా కొనుగోలు చేయడానికి ట్యాప్ చేయండి."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ఇప్పుడు కాదు"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"మేనేజ్ చేయండి"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"పనితీరు బూస్ట్‌ను కొనుగోలు చేయండి."</string>
diff --git a/packages/CarrierDefaultApp/res/values-th/strings.xml b/packages/CarrierDefaultApp/res/values-th/strings.xml
index f20346e..16705d4 100644
--- a/packages/CarrierDefaultApp/res/values-th/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-th/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"ตัวอย่างเช่น หน้าเข้าสู่ระบบอาจไม่ใช่ขององค์กรที่แสดงไว้"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"ดำเนินการต่อผ่านเบราว์เซอร์"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"การเพิ่มประสิทธิภาพ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"ปรับปรุงประสบการณ์การใช้งาน 5G ของคุณ"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s แนะนำให้ซื้อแพ็กเกจเพิ่มประสิทธิภาพ แตะเพื่อซื้อผ่าน %2$s"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ไว้ทีหลัง"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"จัดการ"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"ซื้อการเพิ่มประสิทธิภาพ"</string>
diff --git a/packages/CarrierDefaultApp/res/values-tl/strings.xml b/packages/CarrierDefaultApp/res/values-tl/strings.xml
index 9e8029a..28cd237 100644
--- a/packages/CarrierDefaultApp/res/values-tl/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-tl/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Halimbawa, maaaring hindi pag-aari ng ipinapakitang organisasyon ang page ng login."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Magpatuloy pa rin sa pamamagitan ng browser"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Pag-boost ng performance"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Pagandahin ang iyong karanasan sa 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"Inirerekomenda ng %1$s na bumili ng plan sa performance boost. I-tap para bumili sa pamamagitan ng %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Huwag muna"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Pamahalaan"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Bumili ng pang-boost ng performance."</string>
diff --git a/packages/CarrierDefaultApp/res/values-tr/strings.xml b/packages/CarrierDefaultApp/res/values-tr/strings.xml
index c8fb73b..d35db1d 100644
--- a/packages/CarrierDefaultApp/res/values-tr/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-tr/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Örneğin, giriş sayfası, gösterilen kuruluşa ait olmayabilir."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Yine de tarayıcıyla devam et"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Performans artışı"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G deneyiminizi iyileştirin"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s, performans artırma planı satın almanızı öneriyor. %2$s aracılığıyla satın almak için dokunun."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Şimdi değil"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Yönet"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Performans artışı satın alın."</string>
diff --git a/packages/CarrierDefaultApp/res/values-uk/strings.xml b/packages/CarrierDefaultApp/res/values-uk/strings.xml
index 9927ea0..5d6e34a 100644
--- a/packages/CarrierDefaultApp/res/values-uk/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-uk/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Наприклад, сторінка входу може не належати вказаній організації."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Усе одно продовжити у веб-переглядачі"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Підвищення продуктивності"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Покращте продуктивність свого з’єднання 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s рекомендує придбати тарифний план для підвищення продуктивності. Натисніть, щоб придбати через оператора %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Не зараз"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Керувати"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Придбайте підвищення продуктивності."</string>
diff --git a/packages/CarrierDefaultApp/res/values-ur/strings.xml b/packages/CarrierDefaultApp/res/values-ur/strings.xml
index 681998b..466b6c8 100644
--- a/packages/CarrierDefaultApp/res/values-ur/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ur/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"مثال کے طور پر ہو سکتا ہے کہ لاگ ان صفحہ دکھائی گئی تنظیم سے تعلق نہ رکھتا ہو۔"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"براؤزر کے ذریعے بہرحال جاری رکھیں"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"پرفارمینس بوسٹ"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"‏اپنے 5G تجربے کو بہتر بنائیں"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"‏%1$s ایک پرفارمنس بوسٹ پلان کی تجویز کرتا ہے۔ %2$s استعمال کر کے خریدنے کے لیے تھپتھپائیں۔"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"ابھی نہیں"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"نظم کریں"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"پرفارمینس بوسٹ خریدیں۔"</string>
diff --git a/packages/CarrierDefaultApp/res/values-uz/strings.xml b/packages/CarrierDefaultApp/res/values-uz/strings.xml
index 47006f6..82da958 100644
--- a/packages/CarrierDefaultApp/res/values-uz/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-uz/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Masalan, tizimga kirish sahifasi ko‘rsatilgan tashkilotga tegishli bo‘lmasligi mumkin."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Brauzerda davom ettirish"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Unumdorlikni kuchaytirish"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"5G bilan ishlashni qulaylashtiring"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s unumdorlikni oshiradigan tarif rejasini xarid qilishni tavsiya etadi. %2$s orqali xarid qilish uchun bosing."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Hozir emas"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Boshqarish"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Unumdorlikni kuchaytirish xizmatini xarid qiling."</string>
diff --git a/packages/CarrierDefaultApp/res/values-vi/strings.xml b/packages/CarrierDefaultApp/res/values-vi/strings.xml
index 968b6e1..225e07b 100644
--- a/packages/CarrierDefaultApp/res/values-vi/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-vi/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Ví dụ: trang đăng nhập có thể không thuộc về tổ chức được hiển thị."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Vẫn tiếp tục qua trình duyệt"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"Tăng hiệu suất"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Cải thiện trải nghiệm sử dụng 5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s đề xuất bạn mua gói tăng cường hiệu suất. Nhấn để mua thông qua %2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Để sau"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Quản lý"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Mua gói tăng hiệu suất."</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
index 563117f..5be55bc 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rCN/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"例如,登录页面可能并不属于页面上显示的单位。"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"仍然通过浏览器继续操作"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"性能提升方案"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 体验"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"%1$s建议购买性能提升计划。点按即可通过%2$s进行购买。"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"以后再说"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"购买一份性能提升方案。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
index 7ed0c3c..92f53d3 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rHK/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"例如,登入頁面可能並不屬於所顯示的機構。"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"仍要透過瀏覽器繼續操作"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"效能提升服務"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 體驗"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"「%1$s」建議購買效能提升服務計劃。輕按即可透過「%2$s」購買。"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"暫時不要"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"購買效能提升服務。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
index 332ab9c..6cb4b94 100644
--- a/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zh-rTW/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"例如,登入網頁中顯示的機構可能並非該網頁實際隸屬的機構。"</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"仍要透過瀏覽器繼續操作"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"效能提升方案"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"改善 5G 體驗"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"「%1$s」建議購買效能提升方案,輕觸即可透過「%2$s」購買。"</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"暫時不要"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"管理"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"購買效能提升方案。"</string>
diff --git a/packages/CarrierDefaultApp/res/values-zu/strings.xml b/packages/CarrierDefaultApp/res/values-zu/strings.xml
index ae84695..f8bc50c 100644
--- a/packages/CarrierDefaultApp/res/values-zu/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-zu/strings.xml
@@ -15,8 +15,10 @@
     <string name="ssl_error_example" msgid="6188711843183058764">"Isibonelo, ikhasi lokungena ngemvume kungenzeka lingelenhlangano ebonisiwe."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Qhubeka noma kunjalo ngesiphequluli"</string>
     <string name="performance_boost_notification_channel" msgid="3475440855635538592">"I-boost yokusebenza"</string>
-    <string name="performance_boost_notification_title" msgid="946857427149305992">"Thuthukisa umuzwa wakho we-5G"</string>
-    <string name="performance_boost_notification_detail" msgid="362407668982648351">"I-%1$s incoma ukuthenga uhlelo lokuthuthukisa ukusebenza. Thepha ukuze uthenge nge-%2$s."</string>
+    <!-- no translation found for performance_boost_notification_title (6091638924925876776) -->
+    <skip />
+    <!-- no translation found for performance_boost_notification_detail (86969987181456032) -->
+    <skip />
     <string name="performance_boost_notification_button_not_now" msgid="6459755324243683785">"Hhayi manje"</string>
     <string name="performance_boost_notification_button_manage" msgid="4976836444046497973">"Phatha"</string>
     <string name="slice_purchase_app_label" msgid="7170191659233241166">"Thenga i-boost yokusebenza."</string>
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index 720e46d..e91d35b 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -19,7 +19,7 @@
     <!-- Notification title text for the performance boost notification. -->
     <string name="performance_boost_notification_title">Improve your app experience</string>
     <!-- Notification detail text for the performance boost notification. -->
-    <string name="performance_boost_notification_detail">Tap to visit %s\'s website and learn more.</string>
+    <string name="performance_boost_notification_detail">Tap to visit %s\'s website and learn more</string>
     <!-- Notification button text to cancel the performance boost notification. -->
     <string name="performance_boost_notification_button_not_now">Not now</string>
     <!-- Notification button text to manage the performance boost notification. -->
diff --git a/packages/CredentialManager/res/values-af/strings.xml b/packages/CredentialManager/res/values-af/strings.xml
index 3d32642..f0f040f 100644
--- a/packages/CredentialManager/res/values-af/strings.xml
+++ b/packages/CredentialManager/res/values-af/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Maak sigblad toe"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gaan terug na die vorige bladsy"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Maak toe"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gebruik jou gestoorde wagwoordsleutel vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gebruik jou gestoorde aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Kies ’n gestoorde aanmelding vir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-am/strings.xml b/packages/CredentialManager/res/values-am/strings.xml
index 76533e5..730b0b0 100644
--- a/packages/CredentialManager/res/values-am/strings.xml
+++ b/packages/CredentialManager/res/values-am/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"ሌሎች የይለፍ ቃል አስተዳዳሪዎች"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ሉህን ዝጋ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ወደ ቀዳሚው ገፅ ይመለሱ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ዝጋ"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"የተቀመጠ የይለፍ ቁልፍዎን ለ<xliff:g id="APP_NAME">%1$s</xliff:g> ይጠቀሙ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"የተቀመጠ መግቢያዎን ለ<xliff:g id="APP_NAME">%1$s</xliff:g> ይጠቀሙ?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"የተቆለፉ የሚስጥር ቁልፍ አስተዳዳሪዎች"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ለመክፈት መታ ያድርጉ"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ምንም የመግቢያ ማስረጃ የለም"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> ውስጥ ምንም የመግቢያ መረጃ የለም"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"መግቢያዎችን ያስተዳድሩ"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ከሌላ መሣሪያ"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"የተለየ መሣሪያ ይጠቀሙ"</string>
diff --git a/packages/CredentialManager/res/values-ar/strings.xml b/packages/CredentialManager/res/values-ar/strings.xml
index c5de5c8..666f903 100644
--- a/packages/CredentialManager/res/values-ar/strings.xml
+++ b/packages/CredentialManager/res/values-ar/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"خدمات مدراء كلمات المرور الأخرى"</string>
     <string name="close_sheet" msgid="1393792015338908262">"إغلاق ورقة البيانات"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"العودة إلى الصفحة السابقة"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"إغلاق"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"هل تريد استخدام مفتاح المرور المحفوظ لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"هل تريد استخدام بيانات اعتماد تسجيل الدخول المحفوظة لتطبيق \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"؟"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"خدمات إدارة كلمات المرور المقفولة"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"انقر لفتح القفل."</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ما مِن معلومات تسجيل دخول."</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"ليس هناك معلومات تسجيل دخول في <xliff:g id="SOURCE">%1$s</xliff:g>."</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"إداراة عمليات تسجيل الدخول"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"من جهاز آخر"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"استخدام جهاز مختلف"</string>
diff --git a/packages/CredentialManager/res/values-as/strings.xml b/packages/CredentialManager/res/values-as/strings.xml
index 1ee0a46..6202de5 100644
--- a/packages/CredentialManager/res/values-as/strings.xml
+++ b/packages/CredentialManager/res/values-as/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"শ্বীট বন্ধ কৰক"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"পূৰ্বৱৰ্তী পৃষ্ঠালৈ ঘূৰি যাওক"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"বন্ধ কৰক"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে আপোনাৰ ছেভ হৈ থকা পাছকী ব্যৱহাৰ কৰিবনে?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে আপোনাৰ ছেভ হৈ থকা ছাইন ইন তথ্য ব্যৱহাৰ কৰিবনে?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাবে ছেভ হৈ থকা এটা ছাইন ইন বাছনি কৰক"</string>
diff --git a/packages/CredentialManager/res/values-az/strings.xml b/packages/CredentialManager/res/values-az/strings.xml
index 778b78f..2481a5c 100644
--- a/packages/CredentialManager/res/values-az/strings.xml
+++ b/packages/CredentialManager/res/values-az/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Səhifəni bağlayın"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Əvvəlki səhifəyə qayıdın"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Bağlayın"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış giriş açarı istifadə edilsin?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış girişdən istifadə edilsin?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> üçün yadda saxlanmış girişi seçin"</string>
diff --git a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
index e18aed5..1e7e92e 100644
--- a/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
+++ b/packages/CredentialManager/res/values-b+sr+Latn/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Drugi menadžeri lozinki"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zatvorite tabelu"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vratite se na prethodnu stranicu"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvorite"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite da koristite sačuvani pristupni kôd za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite da koristite sačuvane podatke za prijavljivanje za: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Menadžeri zaključanih lozinki"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite da biste otključali"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka za prijavljivanje"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema podataka za prijavljivanje u: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljajte prijavljivanjima"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Sa drugog uređaja"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Koristi drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-be/strings.xml b/packages/CredentialManager/res/values-be/strings.xml
index d3512ba..f89454a 100644
--- a/packages/CredentialManager/res/values-be/strings.xml
+++ b/packages/CredentialManager/res/values-be/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Іншыя спосабы ўваходу"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Закрыць аркуш"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вярнуцца да папярэдняй старонкі"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Закрыць"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Скарыстаць захаваны ключ доступу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Скарыстаць захаваныя спосабы ўваходу для праграмы \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблакіраваныя спосабы ўваходу"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Націсніце, каб разблакіраваць"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Няма даных для ўваходу"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ва ўліковым запісе <xliff:g id="SOURCE">%1$s</xliff:g> адсутнічае інфармацыя для ўваходу"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кіраваць спосабамі ўваходу"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"З іншай прылады"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Скарыстаць іншую прыладу"</string>
diff --git a/packages/CredentialManager/res/values-bg/strings.xml b/packages/CredentialManager/res/values-bg/strings.xml
index 35926ca..530c823 100644
--- a/packages/CredentialManager/res/values-bg/strings.xml
+++ b/packages/CredentialManager/res/values-bg/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Други мениджъри на пароли"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Затваряне на таблицата"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Назад към предишната страница"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Затваряне"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Да се използва ли запазеният ви код за достъп за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Да се използват ли запазените ви данни за вход за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заключени мениджъри на пароли"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Докоснете, за да отключите"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Няма данни за вход"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> не съдържа данни за вход"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управление на данните за вход"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"От друго устройство"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Използване на друго устройство"</string>
diff --git a/packages/CredentialManager/res/values-bn/strings.xml b/packages/CredentialManager/res/values-bn/strings.xml
index 3273aa4..c3f0e4b 100644
--- a/packages/CredentialManager/res/values-bn/strings.xml
+++ b/packages/CredentialManager/res/values-bn/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"অন্যান্য Password Manager"</string>
     <string name="close_sheet" msgid="1393792015338908262">"শিট বন্ধ করুন"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"আগের পৃষ্ঠায় ফিরে যান"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"বন্ধ করুন"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সেভ করা পাসকী ব্যবহার করবেন?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>-এর জন্য আপনার সেভ করা সাইন-ইন সম্পর্কিত ক্রেডেনশিয়াল ব্যবহার করবেন?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"লক করা Password Manager"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"আনলক করতে ট্যাপ করুন"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"সাইন-ইন সম্পর্কিত তথ্য নেই"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>-এ সাইন-ইন সম্পর্কিত কোনও তথ্য নেই"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"সাইন-ইন করার ক্রেডেনশিয়াল ম্যানেজ করুন"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"অন্য ডিভাইস থেকে"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"আলাদা ডিভাইস ব্যবহার করুন"</string>
diff --git a/packages/CredentialManager/res/values-bs/strings.xml b/packages/CredentialManager/res/values-bs/strings.xml
index 2751651..d980614 100644
--- a/packages/CredentialManager/res/values-bs/strings.xml
+++ b/packages/CredentialManager/res/values-bs/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Drugi upravitelji lozinki"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zatvaranje tabele"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Povratak na prethodnu stranicu"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvaranje"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Koristiti sačuvani pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Koristiti sačuvanu prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zaključani upravitelji lozinki"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite da otključate"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka za prijavu"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema informacija za prijavu na <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljajte prijavama"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"S drugog uređaja"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Upotrijebite drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-ca/strings.xml b/packages/CredentialManager/res/values-ca/strings.xml
index 0d115d5..afbfe50 100644
--- a/packages/CredentialManager/res/values-ca/strings.xml
+++ b/packages/CredentialManager/res/values-ca/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Altres gestors de contrasenyes"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Tanca el full"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Torna a la pàgina anterior"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Tanca"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vols utilitzar la clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vols utilitzar l\'inici de sessió desat per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestors de contrasenyes bloquejats"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Toca per desbloquejar"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sense informació d\'inici de sessió"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Sense informació d\'inici de sessió per a <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestiona els inicis de sessió"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Des d\'un altre dispositiu"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Utilitza un dispositiu diferent"</string>
diff --git a/packages/CredentialManager/res/values-cs/strings.xml b/packages/CredentialManager/res/values-cs/strings.xml
index f3e290b..72e5525 100644
--- a/packages/CredentialManager/res/values-cs/strings.xml
+++ b/packages/CredentialManager/res/values-cs/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Další správci hesel"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zavřít list"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Zpět na předchozí stránku"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zavřít"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Použít uložený přístupový klíč pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Použít uložené přihlášení pro aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Uzamčení správci hesel"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Klepnutím odemknete"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Žádné informace o přihlášení"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> neobsahuje žádné přihlašovací údaje"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Spravovat přihlášení"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Z jiného zařízení"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Použít jiné zařízení"</string>
diff --git a/packages/CredentialManager/res/values-da/strings.xml b/packages/CredentialManager/res/values-da/strings.xml
index 76c8a81..148bba8 100644
--- a/packages/CredentialManager/res/values-da/strings.xml
+++ b/packages/CredentialManager/res/values-da/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Andre adgangskodeadministratorer"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Luk arket"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tilbage til den forrige side"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Luk"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vil du bruge din gemte adgangsnøgle til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vil du bruge din gemte loginmetode til <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låste adgangskodeadministratorer"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tryk for at låse op"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen loginoplysninger"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Der er ingen loginoplysninger i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrer loginmetoder"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Fra en anden enhed"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Brug en anden enhed"</string>
diff --git a/packages/CredentialManager/res/values-de/strings.xml b/packages/CredentialManager/res/values-de/strings.xml
index adcaae4..103a3d2 100644
--- a/packages/CredentialManager/res/values-de/strings.xml
+++ b/packages/CredentialManager/res/values-de/strings.xml
@@ -49,6 +49,8 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Zurück zur vorherigen Seite"</string>
     <!-- no translation found for accessibility_close_button (1163435587545377687) -->
     <skip />
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gespeicherten Passkey für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> verwenden?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
diff --git a/packages/CredentialManager/res/values-el/strings.xml b/packages/CredentialManager/res/values-el/strings.xml
index df1b1a7..8cb3f28 100644
--- a/packages/CredentialManager/res/values-el/strings.xml
+++ b/packages/CredentialManager/res/values-el/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Κλείσιμο φύλλου"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Επιστροφή στην προηγούμενη σελίδα"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Κλείσιμο"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Να χρησιμοποιηθεί το αποθηκευμένο κλειδί πρόσβασης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Να χρησιμοποιηθούν τα αποθηκευμένα στοιχεία σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>;"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Επιλογή αποθηκευμένων στοιχείων σύνδεσης για την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rAU/strings.xml b/packages/CredentialManager/res/values-en-rAU/strings.xml
index e350449c..ffba3ce 100644
--- a/packages/CredentialManager/res/values-en-rAU/strings.xml
+++ b/packages/CredentialManager/res/values-en-rAU/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rCA/strings.xml b/packages/CredentialManager/res/values-en-rCA/strings.xml
index f6ab350..32bbe44 100644
--- a/packages/CredentialManager/res/values-en-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-en-rCA/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rGB/strings.xml b/packages/CredentialManager/res/values-en-rGB/strings.xml
index e350449c..ffba3ce 100644
--- a/packages/CredentialManager/res/values-en-rGB/strings.xml
+++ b/packages/CredentialManager/res/values-en-rGB/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rIN/strings.xml b/packages/CredentialManager/res/values-en-rIN/strings.xml
index e350449c..ffba3ce 100644
--- a/packages/CredentialManager/res/values-en-rIN/strings.xml
+++ b/packages/CredentialManager/res/values-en-rIN/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Close sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Go back to the previous page"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Close"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Use your saved passkey for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Use your saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choose a saved sign-in for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-en-rXC/strings.xml b/packages/CredentialManager/res/values-en-rXC/strings.xml
index 7f5f0c1..49db2fc 100644
--- a/packages/CredentialManager/res/values-en-rXC/strings.xml
+++ b/packages/CredentialManager/res/values-en-rXC/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‎‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‏‎‎Close sheet‎‏‎‎‏‎"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‎‎‎Go back to the previous page‎‏‎‎‏‎"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‏‎‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎Close‎‏‎‎‏‎"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎Use your saved passkey for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‎Use your saved sign-in for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎?‎‏‎‎‏‎"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‏‎‏‎Choose a saved sign-in for ‎‏‎‎‏‏‎<xliff:g id="APP_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
diff --git a/packages/CredentialManager/res/values-es-rUS/strings.xml b/packages/CredentialManager/res/values-es-rUS/strings.xml
index d700ed6..91afadc 100644
--- a/packages/CredentialManager/res/values-es-rUS/strings.xml
+++ b/packages/CredentialManager/res/values-es-rUS/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Otros administradores de contraseñas"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Cerrar hoja"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver a la página anterior"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Cerrar"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"¿Quieres usar tu llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"¿Quieres usar tu acceso guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Administradores de contraseñas bloqueados"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Presiona para desbloquear"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No hay información de acceso"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"No hay información de acceso en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrar accesos"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Desde otro dispositivo"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar otra voz"</string>
diff --git a/packages/CredentialManager/res/values-es/strings.xml b/packages/CredentialManager/res/values-es/strings.xml
index ee056af..b1ff414 100644
--- a/packages/CredentialManager/res/values-es/strings.xml
+++ b/packages/CredentialManager/res/values-es/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Otros gestores de contraseñas"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Cerrar hoja"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver a la página anterior"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Cerrar"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"¿Usar la llave de acceso guardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"¿Usar el inicio de sesión guardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestores de contraseñas bloqueados"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tocar para desbloquear"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"No hay información de inicio de sesión"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"No hay información de inicio de sesión en <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestionar inicios de sesión"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De otro dispositivo"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar otro dispositivo"</string>
diff --git a/packages/CredentialManager/res/values-et/strings.xml b/packages/CredentialManager/res/values-et/strings.xml
index accdea5..5bacae3 100644
--- a/packages/CredentialManager/res/values-et/strings.xml
+++ b/packages/CredentialManager/res/values-et/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Muud paroolihaldurid"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Sule leht"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Minge tagasi eelmisele lehele"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Sule"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Kas kasutada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud pääsuvõtit?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Kas kasutada rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> jaoks salvestatud sisselogimisandmeid?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Lukustatud paroolihaldurid"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Avamiseks puudutage"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sisselogimisteave puudub"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Kontol <xliff:g id="SOURCE">%1$s</xliff:g> puudub sisselogimisteave"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Sisselogimisandmete haldamine"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Muus seadmes"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Kasuta teist seadet"</string>
diff --git a/packages/CredentialManager/res/values-eu/strings.xml b/packages/CredentialManager/res/values-eu/strings.xml
index 18d6532..9052bd2 100644
--- a/packages/CredentialManager/res/values-eu/strings.xml
+++ b/packages/CredentialManager/res/values-eu/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Beste pasahitz-kudeatzaile batzuk"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Itxi orria"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Itzuli aurreko orrira"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Itxi"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gorde duzun sarbide-gakoa erabili nahi duzu?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikaziorako gorde dituzun kredentzialak erabili nahi dituzu?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Blokeatutako pasahitz-kudeatzaileak"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Desblokeatzeko, sakatu hau"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ez dago saioa hasteko informaziorik"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ez dago saioa hasteko informaziorik <xliff:g id="SOURCE">%1$s</xliff:g> kontuan"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Kudeatu kredentzialak"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Beste gailu batean gordetakoak"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Erabili beste gailu bat"</string>
diff --git a/packages/CredentialManager/res/values-fa/strings.xml b/packages/CredentialManager/res/values-fa/strings.xml
index 68ec685..9e01bf0 100644
--- a/packages/CredentialManager/res/values-fa/strings.xml
+++ b/packages/CredentialManager/res/values-fa/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"دیگر مدیران گذرواژه"</string>
     <string name="close_sheet" msgid="1393792015338908262">"بستن برگ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"برگشتن به صفحه قبلی"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"بستن"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"گذرکلید ذخیره‌شده برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده شود؟"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ورود به سیستم ذخیره‌شده برای <xliff:g id="APP_NAME">%1$s</xliff:g> استفاده شود؟"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"مدیران گذرواژه قفل‌شده"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"برای باز کردن قفل ضربه بزنید"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"اطلاعات ورود به سیستم موجود نیست"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"هیچ اطلاعات ورود به سیستمی در <xliff:g id="SOURCE">%1$s</xliff:g> وجود ندارد"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"مدیریت ورود به سیستم‌ها"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"از دستگاهی دیگر"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"استفاده از دستگاه دیگری"</string>
diff --git a/packages/CredentialManager/res/values-fi/strings.xml b/packages/CredentialManager/res/values-fi/strings.xml
index 266a2a9..268dbca 100644
--- a/packages/CredentialManager/res/values-fi/strings.xml
+++ b/packages/CredentialManager/res/values-fi/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Muut salasanojen ylläpitotyökalut"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Sulje taulukko"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Takaisin edelliselle sivulle"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Sulje"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Käytetäänkö tallennettua avainkoodiasi täällä: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Käytetäänkö tallennettuja kirjautumistietoja täällä: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Lukitut salasanojen ylläpitotyökalut"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Avaa napauttamalla"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ei kirjautumistietoja"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ei kirjautumistietoja (<xliff:g id="SOURCE">%1$s</xliff:g>)"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Muuta kirjautumistietoja"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Toiselta laitteelta"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Käytä toista laitetta"</string>
diff --git a/packages/CredentialManager/res/values-fr-rCA/strings.xml b/packages/CredentialManager/res/values-fr-rCA/strings.xml
index 914ee55..d5fd858 100644
--- a/packages/CredentialManager/res/values-fr-rCA/strings.xml
+++ b/packages/CredentialManager/res/values-fr-rCA/strings.xml
@@ -49,6 +49,8 @@
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Retourner à la page précédente"</string>
     <!-- no translation found for accessibility_close_button (1163435587545377687) -->
     <skip />
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Utiliser votre clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Utiliser votre connexion enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Choisir une connexion enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml
index faca62d..95917e1 100644
--- a/packages/CredentialManager/res/values-fr/strings.xml
+++ b/packages/CredentialManager/res/values-fr/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Autres gestionnaires de mots de passe"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Fermer la feuille"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Revenir à la page précédente"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Fermer"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Utiliser votre clé d\'accès enregistrée pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Utiliser vos informations de connexion enregistrées pour <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestionnaires de mots de passe verrouillés"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Appuyer pour déverrouiller"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Aucune information de connexion"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Aucune info de connexion dans <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gérer les connexions"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Depuis un autre appareil"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Utiliser un autre appareil"</string>
diff --git a/packages/CredentialManager/res/values-gl/strings.xml b/packages/CredentialManager/res/values-gl/strings.xml
index 3b2d6f6..88dc4a0 100644
--- a/packages/CredentialManager/res/values-gl/strings.xml
+++ b/packages/CredentialManager/res/values-gl/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Outros xestores de contrasinais"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Pechar folla"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volver á páxina anterior"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Pechar"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Queres usar a clave de acceso gardada para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Queres usar o método de inicio de sesión gardado para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Xestores de contrasinais bloqueados"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Toca para desbloquear"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Sen información de inicio de sesión"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Non hai información de inicio de sesión para <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Xestionar os métodos de inicio de sesión"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Doutro dispositivo"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usar outro dispositivo"</string>
diff --git a/packages/CredentialManager/res/values-gu/strings.xml b/packages/CredentialManager/res/values-gu/strings.xml
index d3339b7..1237483 100644
--- a/packages/CredentialManager/res/values-gu/strings.xml
+++ b/packages/CredentialManager/res/values-gu/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"અન્ય પાસવર્ડ મેનેજર"</string>
     <string name="close_sheet" msgid="1393792015338908262">"શીટ બંધ કરો"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"પાછલા પેજ પર પરત જાઓ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"બંધ કરો"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે શું તમારી સાચવેલી પાસકીનો ઉપયોગ કરીએ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> માટે શું તમારા સાચવેલા સાઇન-ઇનનો ઉપયોગ કરીએ?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"લૉક કરેલા પાસવર્ડ મેનેજર"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"અનલૉક કરવા માટે ટૅપ કરો"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"સાઇન-ઇનની કોઈ માહિતી નથી"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>માં સાઇન-ઇનની કોઈ માહિતી નથી"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"સાઇન-ઇન મેનેજ કરો"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"કોઈ અન્ય ડિવાઇસમાંથી"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"કોઈ અન્ય ડિવાઇસનો ઉપયોગ કરો"</string>
diff --git a/packages/CredentialManager/res/values-hi/strings.xml b/packages/CredentialManager/res/values-hi/strings.xml
index f2790f4..7f3bb49 100644
--- a/packages/CredentialManager/res/values-hi/strings.xml
+++ b/packages/CredentialManager/res/values-hi/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"दूसरे पासवर्ड मैनेजर"</string>
     <string name="close_sheet" msgid="1393792015338908262">"शीट बंद करें"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"पिछले पेज पर वापस जाएं"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"बंद करें"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> पर साइन इन करने के लिए, सेव की गई पासकी का इस्तेमाल करना है?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"क्या आपको <xliff:g id="APP_NAME">%1$s</xliff:g> पर साइन इन करने के लिए, सेव की गई जानकारी का इस्तेमाल करना है?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक किए गए पासवर्ड मैनेजर"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलॉक करने के लिए टैप करें"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन-इन करने से जुड़ी कोई जानकारी उपलब्ध नहीं है"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> में साइन-इन की जानकारी नहीं है"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन इन करने की सुविधा को मैनेज करें"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"किसी दूसरे डिवाइस से"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"दूसरे डिवाइस का इस्तेमाल करें"</string>
diff --git a/packages/CredentialManager/res/values-hr/strings.xml b/packages/CredentialManager/res/values-hr/strings.xml
index 3d813f9..7a8354a 100644
--- a/packages/CredentialManager/res/values-hr/strings.xml
+++ b/packages/CredentialManager/res/values-hr/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Drugi upravitelji zaporki"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zatvaranje lista"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vratite se na prethodnu stranicu"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zatvori"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite li upotrijebiti spremljeni pristupni ključ za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite li upotrijebiti spremljene podatke za prijavu za aplikaciju <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Upravitelji zaključanih zaporki"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Dodirnite za otključavanje"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nema podataka o prijavi"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nema podataka o prijavi u aplikaciji <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Upravljanje prijavama"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Na drugom uređaju"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Upotrijebite drugi uređaj"</string>
diff --git a/packages/CredentialManager/res/values-hu/strings.xml b/packages/CredentialManager/res/values-hu/strings.xml
index e3b0fec..ae136be 100644
--- a/packages/CredentialManager/res/values-hu/strings.xml
+++ b/packages/CredentialManager/res/values-hu/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Egyéb jelszókezelők"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Munkalap bezárása"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Vissza az előző oldalra"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Bezárás"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Szeretné a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz mentett azonosítókulcsot használni?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Szeretné a(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazáshoz mentett bejelentkezési adatait használni?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zárolt jelszókezelők"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Koppintson a feloldáshoz"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nincsenek bejelentkezési adatok"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nem találhatók bejelentkezési adatok itt: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Bejelentkezési adatok kezelése"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Másik eszközről"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Másik eszköz használata"</string>
diff --git a/packages/CredentialManager/res/values-hy/strings.xml b/packages/CredentialManager/res/values-hy/strings.xml
index 6cdc76f..6b7c973 100644
--- a/packages/CredentialManager/res/values-hy/strings.xml
+++ b/packages/CredentialManager/res/values-hy/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Գաղտնաբառերի այլ կառավարիչներ"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Փակել թերթը"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Անցնել նախորդ էջ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Փակել"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Օգտագործե՞լ պահված անցաբառը <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Օգտագործե՞լ մուտքի պահված տվյալները <xliff:g id="APP_NAME">%1$s</xliff:g> հավելվածի համար"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Գաղտնաբառերի կողպված կառավարիչներ"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Հպեք ապակողպելու համար"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Մուտքի տվյալներ չկան"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Մուտքի տվյալներ չկան այստեղ՝ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Մուտքի կառավարում"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Մեկ այլ սարքից"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Օգտագործել այլ սարք"</string>
diff --git a/packages/CredentialManager/res/values-in/strings.xml b/packages/CredentialManager/res/values-in/strings.xml
index f0f0089..9eb3c65 100644
--- a/packages/CredentialManager/res/values-in/strings.xml
+++ b/packages/CredentialManager/res/values-in/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Pengelola sandi lainnya"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Tutup sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kembali ke halaman sebelumnya"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Tutup"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gunakan kunci sandi tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gunakan info login tersimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Pengelola sandi terkunci"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Ketuk untuk membuka kunci"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Tidak ada info login"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Tidak ada info login di <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Kelola login"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Dari perangkat lain"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Gunakan perangkat lain"</string>
diff --git a/packages/CredentialManager/res/values-is/strings.xml b/packages/CredentialManager/res/values-is/strings.xml
index 7ee8b5d..b627058 100644
--- a/packages/CredentialManager/res/values-is/strings.xml
+++ b/packages/CredentialManager/res/values-is/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Önnur aðgangsorðastjórnun"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Loka blaði"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Fara aftur á fyrri síðu"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Loka"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Notað vistaðan aðgangslykil fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Nota vistaða innskráningu fyrir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Læst aðgangsorðastjórnun"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Ýttu til að opna"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Engar innskráningarupplýsingar"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Engar innskráningarupplýsingar á <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Stjórna innskráningu"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Úr öðru tæki"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Nota annað tæki"</string>
diff --git a/packages/CredentialManager/res/values-it/strings.xml b/packages/CredentialManager/res/values-it/strings.xml
index 7f39c1d..9497cea 100644
--- a/packages/CredentialManager/res/values-it/strings.xml
+++ b/packages/CredentialManager/res/values-it/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Altri gestori delle password"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Chiudi il foglio"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Torna alla pagina precedente"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Chiudi"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vuoi usare la passkey salvata per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vuoi usare l\'accesso salvato per <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Gestori delle password bloccati"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tocca per sbloccare"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nessuna informazione di accesso"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Non sono presenti dati di accesso in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestisci gli accessi"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Da un altro dispositivo"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Usa un dispositivo diverso"</string>
diff --git a/packages/CredentialManager/res/values-iw/strings.xml b/packages/CredentialManager/res/values-iw/strings.xml
index 9100b51..9197ac6 100644
--- a/packages/CredentialManager/res/values-iw/strings.xml
+++ b/packages/CredentialManager/res/values-iw/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"מנהלי סיסמאות אחרים"</string>
     <string name="close_sheet" msgid="1393792015338908262">"סגירת הגיליון"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"חזרה לדף הקודם"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"סגירה"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"להשתמש במפתח גישה שנשמר עבור <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"להשתמש בפרטי הכניסה שנשמרו עבור <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"מנהלי סיסמאות נעולים"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"יש להקיש כדי לבטל את הנעילה"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"אין פרטי כניסה"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"אין פרטי כניסה ב-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ניהול כניסות"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ממכשיר אחר"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"צריך להשתמש במכשיר אחר"</string>
diff --git a/packages/CredentialManager/res/values-ja/strings.xml b/packages/CredentialManager/res/values-ja/strings.xml
index c49dd39..3c97777 100644
--- a/packages/CredentialManager/res/values-ja/strings.xml
+++ b/packages/CredentialManager/res/values-ja/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"シートを閉じます"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"前のページに戻ります"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"閉じる"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したパスキーを使用しますか?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したログイン情報を使用しますか?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> の保存したログイン情報の選択"</string>
diff --git a/packages/CredentialManager/res/values-ka/strings.xml b/packages/CredentialManager/res/values-ka/strings.xml
index f5eb7c9..4d0d9f7 100644
--- a/packages/CredentialManager/res/values-ka/strings.xml
+++ b/packages/CredentialManager/res/values-ka/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"ფურცლის დახურვა"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"წინა გვერდზე დაბრუნება"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"დახურვა"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"გსურთ თქვენი დამახსოვრებული წვდომის გასაღების გამოყენება აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"გსურთ თქვენი დამახსოვრებული სისტემაში შესვლის მონაცემების გამოყენება აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"აირჩიეთ სისტემაში შესვლის ინფორმაცია აპისთვის: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-kk/strings.xml b/packages/CredentialManager/res/values-kk/strings.xml
index 8864cb4..4be32d8 100644
--- a/packages/CredentialManager/res/values-kk/strings.xml
+++ b/packages/CredentialManager/res/values-kk/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Басқа құпия сөз менеджерлері"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Парақты жабу"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Алдыңғы бетке оралу"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Жабу"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған кіру кілті пайдаланылсын ба?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> үшін сақталған тіркелу деректері пайдаланылсын ба?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Құлыпталған құпия сөз менеджерлері"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Құлыпты ашу үшін түртіңіз."</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Кіру ақпараты жоқ."</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> аккаунтында кіру туралы ешқандай ақпарат жоқ."</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кіру әрекеттерін басқару"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Басқа құрылғыдан жасау"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Басқа құрылғыны пайдалану"</string>
diff --git a/packages/CredentialManager/res/values-km/strings.xml b/packages/CredentialManager/res/values-km/strings.xml
index f257789..313c0c5 100644
--- a/packages/CredentialManager/res/values-km/strings.xml
+++ b/packages/CredentialManager/res/values-km/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"បិទសន្លឹក"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ត្រឡប់ទៅ​ទំព័រ​មុនវិញ"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"បិទ"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ប្រើកូដសម្ងាត់ដែលបានរក្សាទុករបស់អ្នកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ប្រើការចូល​គណនីដែលបានរក្សាទុករបស់អ្នកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g> ឬ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"ជ្រើសរើសការចូលគណនីដែលបានរក្សាទុកសម្រាប់ <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-kn/strings.xml b/packages/CredentialManager/res/values-kn/strings.xml
index c41bd63..750c51b 100644
--- a/packages/CredentialManager/res/values-kn/strings.xml
+++ b/packages/CredentialManager/res/values-kn/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"ಶೀಟ್ ಮುಚ್ಚಿರಿ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ಹಿಂದಿನ ಪುಟಕ್ಕೆ ಹಿಂದಿರುಗಿ"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"ಮುಚ್ಚಿರಿ"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ನಿಮ್ಮ ಪಾಸ್‌ಕೀ ಅನ್ನು ಬಳಸಬೇಕೆ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ನಿಮ್ಮ ಸೈನ್-ಇನ್ ಅನ್ನು ಬಳಸಬೇಕೆ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಗಾಗಿ ಉಳಿಸಲಾದ ಸೈನ್-ಇನ್ ಮಾಹಿತಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
diff --git a/packages/CredentialManager/res/values-ko/strings.xml b/packages/CredentialManager/res/values-ko/strings.xml
index 20b734a..89b5a3f 100644
--- a/packages/CredentialManager/res/values-ko/strings.xml
+++ b/packages/CredentialManager/res/values-ko/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"기타 비밀번호 관리자"</string>
     <string name="close_sheet" msgid="1393792015338908262">"시트 닫기"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"이전 페이지로 돌아가기"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"닫기"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용 저장된 패스키를 사용하시겠습니까?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱용 저장된 로그인 정보를 사용하시겠습니까?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"잠긴 비밀번호 관리자"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"탭하여 잠금 해제"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"로그인 정보 없음"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>의 로그인 정보 없음"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"로그인 관리"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"다른 기기에서"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"다른 기기 사용"</string>
diff --git a/packages/CredentialManager/res/values-ky/strings.xml b/packages/CredentialManager/res/values-ky/strings.xml
index 895d0e7..3e172b4 100644
--- a/packages/CredentialManager/res/values-ky/strings.xml
+++ b/packages/CredentialManager/res/values-ky/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Башка сырсөздөрдү башкаргычтар"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Баракты жабуу"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Мурунку бетке кайтуу"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Жабуу"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган мүмкүндүк алуу ачкычын колдоносузбу?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> үчүн сакталган кирүү параметрин колдоносузбу?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Кулпуланган сырсөздөрдү башкаргычтар"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Кулпусун ачуу үчүн таптаңыз"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Аккаунтка кирүү тууралуу маалымат жок"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> аккаунтунда кирүү маалыматы жок"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Кирүү параметрлерин тескөө"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Башка түзмөктөн"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Башка түзмөктү колдонуу"</string>
diff --git a/packages/CredentialManager/res/values-lo/strings.xml b/packages/CredentialManager/res/values-lo/strings.xml
index 757bf13..f08d522 100644
--- a/packages/CredentialManager/res/values-lo/strings.xml
+++ b/packages/CredentialManager/res/values-lo/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"ຕົວຈັດການລະຫັດຜ່ານອື່ນໆ"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ປິດຊີດ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ກັບຄືນໄປຫາໜ້າກ່ອນໜ້ານີ້"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ປິດ"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ໃຊ້ກະແຈຜ່ານທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ໃຊ້ການເຂົ້າສູ່ລະບົບທີ່ບັນທຶກໄວ້ຂອງທ່ານສຳລັບ <xliff:g id="APP_NAME">%1$s</xliff:g> ບໍ?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ຕົວຈັດການລະຫັດຜ່ານທີ່ລັອກໄວ້"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ແຕະເພື່ອປົດລັອກ"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ບໍ່ມີຂໍ້ມູນການເຂົ້າສູ່ລະບົບ"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"ບໍ່ມີຂໍ້ມູນການເຂົ້າສູ່ລະບົບໃນ <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ຈັດການການເຂົ້າສູ່ລະບົບ"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ຈາກອຸປະກອນອື່ນ"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ໃຊ້ອຸປະກອນອື່ນ"</string>
diff --git a/packages/CredentialManager/res/values-lt/strings.xml b/packages/CredentialManager/res/values-lt/strings.xml
index d75993f..71b50a8 100644
--- a/packages/CredentialManager/res/values-lt/strings.xml
+++ b/packages/CredentialManager/res/values-lt/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Kitos slaptažodžių tvarkyklės"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Uždaryti lapą"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Grįžti į ankstesnį puslapį"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Uždaryti"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Naudoti išsaugotą „passkey“ programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Naudoti išsaugotą prisijungimo informaciją programai „<xliff:g id="APP_NAME">%1$s</xliff:g>“?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Užrakintos slaptažodžių tvarkyklės"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Palieskite, kad atrakintumėte"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Prisijungimo informacijos nėra"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nėra prisijungimo informacijos <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Tvarkyti prisijungimo informaciją"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Naudojant kitą įrenginį"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Naudoti kitą įrenginį"</string>
diff --git a/packages/CredentialManager/res/values-lv/strings.xml b/packages/CredentialManager/res/values-lv/strings.xml
index 01c6d55..86a7b8a 100644
--- a/packages/CredentialManager/res/values-lv/strings.xml
+++ b/packages/CredentialManager/res/values-lv/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Citi paroļu pārvaldnieki"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Aizvērt lapu"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Atgriezties iepriekšējā lapā"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Aizvērt"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vai izmantot saglabāto piekļuves atslēgu lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vai izmantot saglabāto pierakstīšanās informāciju lietotnei <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Paroļu pārvaldnieki, kuros nepieciešams autentificēties"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Pieskarieties, lai atbloķētu"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nav pierakstīšanās informācijas"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Kontā <xliff:g id="SOURCE">%1$s</xliff:g> nav pierakstīšanās informācijas."</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Pierakstīšanās informācijas pārvaldība"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"No citas ierīces"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Izmantot citu ierīci"</string>
diff --git a/packages/CredentialManager/res/values-mk/strings.xml b/packages/CredentialManager/res/values-mk/strings.xml
index a844bc9..393bca1 100644
--- a/packages/CredentialManager/res/values-mk/strings.xml
+++ b/packages/CredentialManager/res/values-mk/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Други управници со лозинки"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Затворете го листот"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Врати се на претходната страница"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Затвори"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Да се користи вашиот зачуван криптографски клуч за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Да се користи вашето зачувано најавување за <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заклучени управници со лозинки"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Допрете за да отклучите"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Нема податоци за најавување"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Нема податоци за најавување во <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управувајте со најавувањата"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Од друг уред"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Употребете друг уред"</string>
diff --git a/packages/CredentialManager/res/values-ml/strings.xml b/packages/CredentialManager/res/values-ml/strings.xml
index de88b28..efe614c 100644
--- a/packages/CredentialManager/res/values-ml/strings.xml
+++ b/packages/CredentialManager/res/values-ml/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"ഷീറ്റ് അടയ്ക്കുക"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"മുമ്പത്തെ പേജിലേക്ക് മടങ്ങുക"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"അടയ്ക്കുക"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി നിങ്ങൾ സംരക്ഷിച്ച പാസ്‌കീ ഉപയോഗിക്കണോ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി നിങ്ങൾ സംരക്ഷിച്ച സൈൻ ഇൻ ഉപയോഗിക്കണോ?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> എന്നതിനായി ഒരു സംരക്ഷിച്ച സൈൻ ഇൻ തിരഞ്ഞെടുക്കുക"</string>
diff --git a/packages/CredentialManager/res/values-mn/strings.xml b/packages/CredentialManager/res/values-mn/strings.xml
index ee5d66f..6c7ba7a 100644
--- a/packages/CredentialManager/res/values-mn/strings.xml
+++ b/packages/CredentialManager/res/values-mn/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Нууц үгний бусад менежер"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Хүснэгтийг хаах"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Өмнөх хуудас руу буцах"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Хаах"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д өөрийн хадгалсан passkey-г ашиглах уу?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g>-д хадгалсан нэвтрэх мэдээллээ ашиглах уу?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Түгжээтэй нууц үгний менежерүүд"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Түгжээг тайлахын тулд товшино уу"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ямар ч нэвтрэх мэдээлэл байхгүй"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>-д ямар ч нэвтрэх мэдээлэл алга"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Нэвтрэлтийг удирдах"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Өөр төхөөрөмжөөс"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Өөр төхөөрөмж ашиглах"</string>
diff --git a/packages/CredentialManager/res/values-mr/strings.xml b/packages/CredentialManager/res/values-mr/strings.xml
index bc03212..ca0480c 100644
--- a/packages/CredentialManager/res/values-mr/strings.xml
+++ b/packages/CredentialManager/res/values-mr/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"इतर पासवर्ड व्यवस्थापक"</string>
     <string name="close_sheet" msgid="1393792015338908262">"शीट बंद करा"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"मागील पेजवर परत जा"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"बंद करा"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमची सेव्ह केलेली पासकी वापरायची का?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> साठी तुमचे सेव्ह केलेले साइन-इन वापरायचे का?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लॉक केलेले पासवर्ड व्यवस्थापक"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलॉक करण्यासाठी टॅप करा"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन-इन माहिती नाही"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> मध्ये कोणतीही साइन-इन माहिती नाही"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन-इन व्यवस्थापित करा"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"दुसऱ्या डिव्हाइस वरून"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"वेगळे डिव्हाइस वापरा"</string>
diff --git a/packages/CredentialManager/res/values-ms/strings.xml b/packages/CredentialManager/res/values-ms/strings.xml
index ab2d9536..7719f91 100644
--- a/packages/CredentialManager/res/values-ms/strings.xml
+++ b/packages/CredentialManager/res/values-ms/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Tutup helaian"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kembali ke halaman sebelumnya"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Tutup"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gunakan kunci laluan anda yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gunakan maklumat log masuk anda yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Pilih log masuk yang telah disimpan untuk <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-my/strings.xml b/packages/CredentialManager/res/values-my/strings.xml
index 92a9e49..9b60d5c 100644
--- a/packages/CredentialManager/res/values-my/strings.xml
+++ b/packages/CredentialManager/res/values-my/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"အခြားစကားဝှက်မန်နေဂျာများ"</string>
     <string name="close_sheet" msgid="1393792015338908262">"စာမျက်နှာ ပိတ်ရန်"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ယခင်စာမျက်နှာကို ပြန်သွားပါ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ပိတ်ရန်"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသောလျှို့ဝှက်ကီး သုံးမလား။"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> အတွက် သိမ်းထားသောလက်မှတ်ထိုးဝင်မှု သုံးမလား။"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"လော့ခ်ချထားသည့် စကားဝှက်မန်နေဂျာများ"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ဖွင့်ရန် တို့ပါ"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"လက်မှတ်ထိုးဝင်သည့် အချက်အလက် မရှိပါ"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> တွင် လက်မှတ်ထိုးဝင်ရန်အချက်အလက် မရှိပါ"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"လက်မှတ်ထိုးဝင်မှုများ စီမံခြင်း"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"စက်နောက်တစ်ခုမှ"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"အခြားစက်သုံးရန်"</string>
diff --git a/packages/CredentialManager/res/values-nb/strings.xml b/packages/CredentialManager/res/values-nb/strings.xml
index ac8f7c1..88692cb 100644
--- a/packages/CredentialManager/res/values-nb/strings.xml
+++ b/packages/CredentialManager/res/values-nb/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Andre løsninger for passordlagring"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Lukk arket"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tilbake til den forrige siden"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Lukk"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vil du bruke den lagrede tilgangsnøkkelen for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vil du bruke den lagrede påloggingen for <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låste løsninger for passordlagring"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Trykk for å låse opp"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen påloggingsinformasjon"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Ingen påloggingsinformasjon i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Administrer pålogginger"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Fra en annen enhet"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Bruk en annen enhet"</string>
diff --git a/packages/CredentialManager/res/values-ne/strings.xml b/packages/CredentialManager/res/values-ne/strings.xml
index 70ae649..45c9f8c 100644
--- a/packages/CredentialManager/res/values-ne/strings.xml
+++ b/packages/CredentialManager/res/values-ne/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"अन्य पासवर्ड म्यानेजरहरू"</string>
     <string name="close_sheet" msgid="1393792015338908262">"पाना बन्द गर्नुहोस्"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"अघिल्लो पेजमा फर्कनुहोस्"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"बन्द गर्नुहोस्"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"आफूले सेभ गरेको पासकी प्रयोग गरी <xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्ने हो?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"आफूले सेभ गरेको साइन इनसम्बन्धी जानकारी प्रयोग गरी <xliff:g id="APP_NAME">%1$s</xliff:g> मा साइन इन गर्ने हो?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"लक गरिएका पासवर्ड म्यानेजरहरू"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"अनलक गर्न ट्याप गर्नुहोस्"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"साइन गर्न प्रयोग गरिनु पर्ने जानकारी उपलब्ध छैन"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> मा साइन इन गर्नेसम्बन्धी कुनै पनि जानकारी छैन"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"साइन इनसम्बन्धी विकल्पहरू व्यवस्थापन गर्नुहोस्"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"अर्को डिभाइसका लागि"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"अर्कै डिभाइस प्रयोग गरी हेर्नुहोस्"</string>
diff --git a/packages/CredentialManager/res/values-nl/strings.xml b/packages/CredentialManager/res/values-nl/strings.xml
index f3d7288..32307ea2 100644
--- a/packages/CredentialManager/res/values-nl/strings.xml
+++ b/packages/CredentialManager/res/values-nl/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Andere wachtwoordmanagers"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Blad sluiten"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Ga terug naar de vorige pagina"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Sluiten"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Je opgeslagen toegangssleutel voor <xliff:g id="APP_NAME">%1$s</xliff:g> gebruiken?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Je opgeslagen inloggegevens voor <xliff:g id="APP_NAME">%1$s</xliff:g> gebruiken?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Vergrendelde wachtwoordmanagers"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tik om te ontgrendelen"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Geen inloggegevens"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Geen inloggevens in <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Inloggegevens beheren"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Via een ander apparaat"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Een ander apparaat gebruiken"</string>
diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml
index 539b3dd..953e9b2 100644
--- a/packages/CredentialManager/res/values-or/strings.xml
+++ b/packages/CredentialManager/res/values-or/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"ଅନ୍ୟ Password Manager"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ସିଟ ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ପୂର୍ବବର୍ତ୍ତୀ ପୃଷ୍ଠାକୁ ଫେରନ୍ତୁ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ବନ୍ଦ କରନ୍ତୁ"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଆପଣଙ୍କ ପାସକୀ ବ୍ୟବହାର କରିବେ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ପାଇଁ ସେଭ କରାଯାଇଥିବା ଆପଣଙ୍କ ସାଇନ-ଇନ ବ୍ୟବହାର କରିବେ?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ଲକ ଥିବା Password Manager"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ଅନଲକ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"କୌଣସି ସାଇନ-ଇନ ସୂଚନା ନାହିଁ"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>ରେ କୌଣସି ସାଇନ-ଇନ ସୂଚନା ନାହିଁ"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ସାଇନ-ଇନ ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ଅନ୍ୟ ଏକ ଡିଭାଇସରୁ"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ଏକ ଭିନ୍ନ ଡିଭାଇସ ବ୍ୟବହାର କରନ୍ତୁ"</string>
diff --git a/packages/CredentialManager/res/values-pa/strings.xml b/packages/CredentialManager/res/values-pa/strings.xml
index 7e4676a..2dd6a2c 100644
--- a/packages/CredentialManager/res/values-pa/strings.xml
+++ b/packages/CredentialManager/res/values-pa/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"ਹੋਰ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ਸ਼ੀਟ ਬੰਦ ਕਰੋ"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"ਪਿਛਲੇ ਪੰਨੇ \'ਤੇ ਵਾਪਸ ਜਾਓ"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ਬੰਦ ਕਰੋ"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣੀ ਰੱਖਿਅਤ ਕੀਤੀ ਪਾਸਕੀ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ਕੀ <xliff:g id="APP_NAME">%1$s</xliff:g> ਲਈ ਆਪਣੀ ਰੱਖਿਅਤ ਕੀਤੀ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਦੀ ਵਰਤੋਂ ਕਰਨੀ ਹੈ?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"ਲਾਕ ਕੀਤੇ ਪਾਸਵਰਡ ਪ੍ਰਬੰਧਕ"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> ਵਿੱਚ ਕੋਈ ਸਾਈਨ-ਇਨ ਜਾਣਕਾਰੀ ਨਹੀਂ"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"ਸਾਈਨ-ਇਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"ਹੋਰ ਡੀਵਾਈਸ ਤੋਂ"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ਵੱਖਰੇ ਡੀਵਾਈਸ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string>
diff --git a/packages/CredentialManager/res/values-pl/strings.xml b/packages/CredentialManager/res/values-pl/strings.xml
index c77d846..74a0d8f 100644
--- a/packages/CredentialManager/res/values-pl/strings.xml
+++ b/packages/CredentialManager/res/values-pl/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Inne menedżery haseł"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zamknij arkusz"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Wróć do poprzedniej strony"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zamknij"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Użyć zapisanego klucza dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Użyć zapisanych danych logowania dla aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Zablokowane menedżery haseł"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Kliknij, aby odblokować"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Brak danych logowania"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g>: brak danych logowania"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Zarządzanie danymi logowania"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Na innym urządzeniu"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Użyj innego urządzenia"</string>
diff --git a/packages/CredentialManager/res/values-pt-rBR/strings.xml b/packages/CredentialManager/res/values-pt-rBR/strings.xml
index 90433e1..9eaf99b 100644
--- a/packages/CredentialManager/res/values-pt-rBR/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rBR/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Fechar página"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Voltar à página anterior"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar sua chave de acesso salva para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar suas informações de login salvas para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolher um login salvo para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-pt-rPT/strings.xml b/packages/CredentialManager/res/values-pt-rPT/strings.xml
index 1abc85d..ad927e0 100644
--- a/packages/CredentialManager/res/values-pt-rPT/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rPT/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Fechar folha"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Volte à página anterior"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar a sua token de acesso guardada na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar o seu início de sessão guardado na app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolha um início de sessão guardado para a app <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-pt/strings.xml b/packages/CredentialManager/res/values-pt/strings.xml
index 90433e1..9eaf99b 100644
--- a/packages/CredentialManager/res/values-pt/strings.xml
+++ b/packages/CredentialManager/res/values-pt/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Fechar página"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Voltar à página anterior"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Fechar"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Usar sua chave de acesso salva para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Usar suas informações de login salvas para <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Escolher um login salvo para <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-ro/strings.xml b/packages/CredentialManager/res/values-ro/strings.xml
index 11b3b49..198ff1d 100644
--- a/packages/CredentialManager/res/values-ro/strings.xml
+++ b/packages/CredentialManager/res/values-ro/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Alți manageri de parole"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Închide foaia"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Revino la pagina precedentă"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Închide"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Folosești cheia de acces salvată pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Folosești datele de conectare salvate pentru <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Manageri de parole blocate"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Atinge pentru a debloca"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Fără informații de conectare"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nu există informații de conectare în contul <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Gestionează acreditările"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"De pe alt dispozitiv"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Folosește alt dispozitiv"</string>
diff --git a/packages/CredentialManager/res/values-ru/strings.xml b/packages/CredentialManager/res/values-ru/strings.xml
index c7d253e..846df54 100644
--- a/packages/CredentialManager/res/values-ru/strings.xml
+++ b/packages/CredentialManager/res/values-ru/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Другие менеджеры паролей"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Закрыть лист"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вернуться на предыдущую страницу"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Закрыть"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Использовать сохраненный ключ доступа для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Использовать сохраненные учетные данные для приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\"?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблокированные менеджеры паролей"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Нажмите для разблокировки"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Необходимо ввести учетные данные"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"В аккаунте <xliff:g id="SOURCE">%1$s</xliff:g> нет учетных данных"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управление входом"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"С другого устройства"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Использовать другое устройство"</string>
diff --git a/packages/CredentialManager/res/values-si/strings.xml b/packages/CredentialManager/res/values-si/strings.xml
index 36ce3f8..1df8ea2 100644
--- a/packages/CredentialManager/res/values-si/strings.xml
+++ b/packages/CredentialManager/res/values-si/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"වෙනත් මුරපද කළමනාකරුවන්"</string>
     <string name="close_sheet" msgid="1393792015338908262">"පත්‍රය වසන්න"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"පෙර පිටුවට ආපසු යන්න"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"වසන්න"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි මුරයතුර භාවිතා කරන්න ද?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> සඳහා ඔබේ සුරැකි පුරනය භාවිතා කරන්න ද?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"අගුළු දැමූ මුරපද කළමනාකරුවන්"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"අගුළු හැරීමට තට්ටු කරන්න"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"පුරනය වීමේ තතු නැත"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> තුළ පුරනය වීමේ තතු නැත"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"පුරනය වීම් කළමනාකරණය කරන්න"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"වෙනත් උපාංගයකින්"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"වෙනස් උපාංගයක් භාවිතා කරන්න"</string>
diff --git a/packages/CredentialManager/res/values-sk/strings.xml b/packages/CredentialManager/res/values-sk/strings.xml
index 09bf265..eb18796 100644
--- a/packages/CredentialManager/res/values-sk/strings.xml
+++ b/packages/CredentialManager/res/values-sk/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Iní správcovia hesiel"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Zavrieť hárok"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Prejsť späť na predchádzajúcu stránku"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Zavrieť"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Chcete pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> použiť uložený prístupový kľúč?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Chcete pre aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g> použiť uložené prihlasovacie údaje?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Správcovia uzamknutých hesiel"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Odomknúť klepnutím"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Žiadne prihlasovacie údaje"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Žiadne prihlasovacie údaje v zdroji <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Spravovať prihlasovacie údaje"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Z iného zariadenia"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Použiť iné zariadenie"</string>
diff --git a/packages/CredentialManager/res/values-sl/strings.xml b/packages/CredentialManager/res/values-sl/strings.xml
index 29b6410..15bcbae 100644
--- a/packages/CredentialManager/res/values-sl/strings.xml
+++ b/packages/CredentialManager/res/values-sl/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Zapri list"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Nazaj na prejšnjo stran"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Zapri"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Želite uporabiti shranjeni ključ za dostop do aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Želite uporabiti shranjene podatke za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"Izberite shranjene podatke za prijavo v aplikacijo <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index 6650668..1e46538 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Menaxherët e tjerë të fjalëkalimeve"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Mbyll fletën"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Kthehu te faqja e mëparshme"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Mbyll"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Të përdoret fjalëkalimi yt i ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Të përdoret identifikimi yt i ruajtur për <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Menaxherët e fjalëkalimeve të kyçura"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Trokit për të shkyçur"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Nuk ka informacione për identifikimin"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Nuk ka informacione regjistrimi në <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Identifikimet e menaxhimit"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Nga një pajisje tjetër"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Përdor një pajisje tjetër"</string>
diff --git a/packages/CredentialManager/res/values-sr/strings.xml b/packages/CredentialManager/res/values-sr/strings.xml
index 877d45c..bbb5463 100644
--- a/packages/CredentialManager/res/values-sr/strings.xml
+++ b/packages/CredentialManager/res/values-sr/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Други менаџери лозинки"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Затворите табелу"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Вратите се на претходну страницу"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Затворите"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Желите да користите сачувани приступни кôд за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Желите да користите сачуване податке за пријављивање за: <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Менаџери закључаних лозинки"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Додирните да бисте откључали"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Нема података за пријављивање"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Нема података за пријављивање у: <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Управљајте пријављивањима"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Са другог уређаја"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Користи други уређај"</string>
diff --git a/packages/CredentialManager/res/values-sv/strings.xml b/packages/CredentialManager/res/values-sv/strings.xml
index 9ec317e..3d85e14 100644
--- a/packages/CredentialManager/res/values-sv/strings.xml
+++ b/packages/CredentialManager/res/values-sv/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Andra lösenordshanterare"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Stäng kalkylarket"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Gå tillbaka till föregående sida"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Stäng"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Vill du använda din sparade nyckel för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Vill du använda dina sparade inloggningsuppgifter för <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Låsta lösenordshanterare"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Tryck för att låsa upp"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Ingen inloggningsinformation"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Det finns inga inloggningsuppgifter i <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Hantera inloggningar"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Via en annan enhet"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Använd en annan enhet"</string>
diff --git a/packages/CredentialManager/res/values-sw/strings.xml b/packages/CredentialManager/res/values-sw/strings.xml
index 1a5499c..f0f1db5 100644
--- a/packages/CredentialManager/res/values-sw/strings.xml
+++ b/packages/CredentialManager/res/values-sw/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Vidhibiti vinginevyo vya manenosiri"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Funga laha"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Rudi kwenye ukurasa uliotangulia"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Funga"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Ungependa kutumia ufunguo wa siri uliohifadhiwa wa<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Ungependa kutumia kitambulisho kilichohifadhiwa cha kuingia katika akaunti ya <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Vidhibiti vya manenosiri vilivyofungwa"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Gusa ili ufungue"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Hakuna maelezo ya kuingia katika akaunti"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Hakuna maelezo ya kuingia katika akaunti kwenye <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Dhibiti michakato ya kuingia katika akaunti"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Kutoka kwenye kifaa kingine"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Tumia kifaa tofauti"</string>
diff --git a/packages/CredentialManager/res/values-ta/strings.xml b/packages/CredentialManager/res/values-ta/strings.xml
index 19a871f..09a4fcb 100644
--- a/packages/CredentialManager/res/values-ta/strings.xml
+++ b/packages/CredentialManager/res/values-ta/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"பிற கடவுச்சொல் நிர்வாகிகள்"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ஷீட்டை மூடும்"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"முந்தைய பக்கத்திற்குச் செல்லும்"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"மூடும்"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு ஏற்கெனவே சேமிக்கப்பட்ட கடவுக்குறியீட்டைப் பயன்படுத்தவா?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸுக்கு ஏற்கெனவே சேமிக்கப்பட்ட உள்நுழைவுத் தகவலைப் பயன்படுத்தவா?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"பூட்டப்பட்ட கடவுச்சொல் நிர்வாகிகள்"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"அன்லாக் செய்ய தட்டவும்"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"உள்நுழைவு விவரங்கள் இல்லை"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> கணக்கில் உள்நுழைவு விவரங்கள் இல்லை"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"உள்நுழைவுகளை நிர்வகித்தல்"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"மற்றொரு சாதனத்திலிருந்து பயன்படுத்து"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"வேறு சாதனத்தைப் பயன்படுத்து"</string>
diff --git a/packages/CredentialManager/res/values-te/strings.xml b/packages/CredentialManager/res/values-te/strings.xml
index 04ee0fe..e93ff20 100644
--- a/packages/CredentialManager/res/values-te/strings.xml
+++ b/packages/CredentialManager/res/values-te/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"షీట్‌ను మూసివేయండి"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"మునుపటి పేజీకి తిరిగి వెళ్లండి"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"మూసివేస్తుంది"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీ సేవ్ చేసిన పాస్-కీ వివరాలను ఉపయోగించాలా?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం మీరు సేవ్ చేసిన సైన్ ఇన్ వివరాలను ఉపయోగించాలా?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> కోసం సేవ్ చేసిన సైన్ ఇన్ వివరాలను ఎంచుకోండి"</string>
diff --git a/packages/CredentialManager/res/values-th/strings.xml b/packages/CredentialManager/res/values-th/strings.xml
index 29e87a0..e44a66d 100644
--- a/packages/CredentialManager/res/values-th/strings.xml
+++ b/packages/CredentialManager/res/values-th/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"เครื่องมือจัดการรหัสผ่านอื่นๆ"</string>
     <string name="close_sheet" msgid="1393792015338908262">"ปิดชีต"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"กลับไปยังหน้าก่อนหน้า"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"ปิด"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"ใช้พาสคีย์ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" ใช่ไหม"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"ใช้การลงชื่อเข้าใช้ที่บันทึกไว้สำหรับ \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" ใช่ไหม"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"เครื่องมือจัดการรหัสผ่านที่ล็อกไว้"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"แตะเพื่อปลดล็อก"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"ไม่มีข้อมูลการลงชื่อเข้าใช้"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"ไม่มีข้อมูลการลงชื่อเข้าใช้ใน <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"จัดการการลงชื่อเข้าใช้"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"จากอุปกรณ์อื่น"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ใช้อุปกรณ์อื่น"</string>
diff --git a/packages/CredentialManager/res/values-tl/strings.xml b/packages/CredentialManager/res/values-tl/strings.xml
index 773039f..6b48af1 100644
--- a/packages/CredentialManager/res/values-tl/strings.xml
+++ b/packages/CredentialManager/res/values-tl/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Iba pang password manager"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Isara ang sheet"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Bumalik sa nakaraang page"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Isara"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Gamitin ang iyong naka-save na passkey para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Gamitin ang iyong naka-save na sign-in para sa <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Mga naka-lock na password manager"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"I-tap para i-unlock"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Walang impormasyon sa pag-sign in"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Walang impormasyon sa pag-sign in sa <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Pamahalaan ang mga sign-in"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Mula sa ibang device"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Gumamit ng ibang device"</string>
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index 083add3..b0a354c 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Diğer şifre yöneticileri"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Sayfayı kapat"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Önceki sayfaya geri dön"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Kapat"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı şifre anahtarınız kullanılsın mı?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı oturum açma bilgileriniz kullanılsın mı?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Kilitli şifre yöneticileri"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Kilidi açmak için dokunun"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Oturum açma bilgisi yok"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> hesabında oturum açma bilgisi yok"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Oturum açma bilgilerini yönetin"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Başka bir cihazdan"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Farklı bir cihaz kullan"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index dd112e03..ec12bc6 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Інші менеджери паролів"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Закрити аркуш"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Повернутися на попередню сторінку"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Закрити"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Використати збережений ключ доступу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Використати збережені дані для входу для додатка <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблоковані менеджери паролів"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Торкніться, щоб розблокувати"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Немає даних для входу"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Немає даних для входу в обліковий запис <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Керування даними для входу"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"З іншого пристрою"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Використовувати інший пристрій"</string>
diff --git a/packages/CredentialManager/res/values-ur/strings.xml b/packages/CredentialManager/res/values-ur/strings.xml
index 3a704fe..b4bf77f 100644
--- a/packages/CredentialManager/res/values-ur/strings.xml
+++ b/packages/CredentialManager/res/values-ur/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"دیگر پاس ورڈ مینیجرز"</string>
     <string name="close_sheet" msgid="1393792015338908262">"شیٹ بند کریں"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"گزشتہ صفحے پر واپس جائیں"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"بند کریں"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اپنی محفوظ کردہ پاس کی استعمال کریں؟"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> کے لیے اپنے محفوظ کردہ سائن ان کو استعمال کریں؟"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"مقفل کردہ پاس ورڈ مینیجرز"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"غیر مقفل کرنے کیلئے تھپتھپائیں"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"سائن ان کی کوئی معلومات نہیں"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> میں سائن ان کی کوئی معلومات نہیں ہے"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"سائن انز کا نظم کریں"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"دوسرے آلے سے"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"ایک مختلف آلہ استعمال کریں"</string>
diff --git a/packages/CredentialManager/res/values-uz/strings.xml b/packages/CredentialManager/res/values-uz/strings.xml
index 8248d52..92c40ee 100644
--- a/packages/CredentialManager/res/values-uz/strings.xml
+++ b/packages/CredentialManager/res/values-uz/strings.xml
@@ -48,6 +48,8 @@
     <string name="close_sheet" msgid="1393792015338908262">"Varaqni yopish"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Avvalgi sahifaga qaytish"</string>
     <string name="accessibility_close_button" msgid="1163435587545377687">"Yopish"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
+    <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan kalit ishlatilsinmi?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"<xliff:g id="APP_NAME">%1$s</xliff:g> uchun saqlangan maʼlumotlar ishlatilsinmi?"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="1361715440877613701">"<xliff:g id="APP_NAME">%1$s</xliff:g> hisob maʼlumotlarini tanlang"</string>
diff --git a/packages/CredentialManager/res/values-vi/strings.xml b/packages/CredentialManager/res/values-vi/strings.xml
index 058e207..dd0aeed 100644
--- a/packages/CredentialManager/res/values-vi/strings.xml
+++ b/packages/CredentialManager/res/values-vi/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Trình quản lý mật khẩu khác"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Đóng trang tính"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Quay lại trang trước"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Đóng"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Dùng mã xác thực bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Dùng thông tin đăng nhập bạn đã lưu cho <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Trình quản lý mật khẩu đã khoá"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Nhấn để mở khoá"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Không có thông tin đăng nhập"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Không có thông tin đăng nhập trong <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Quản lý thông tin đăng nhập"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Từ một thiết bị khác"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Dùng thiết bị khác"</string>
diff --git a/packages/CredentialManager/res/values-zh-rCN/strings.xml b/packages/CredentialManager/res/values-zh-rCN/strings.xml
index 976ef57..87bdce3e 100644
--- a/packages/CredentialManager/res/values-zh-rCN/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rCN/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"其他密码管理工具"</string>
     <string name="close_sheet" msgid="1393792015338908262">"关闭工作表"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一页"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"关闭"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"将您已保存的通行密钥用于<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"将您已保存的登录信息用于<xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已锁定的密码管理工具"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"点按即可解锁"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"无登录信息"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中没有任何登录信息"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登录信息"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"通过另一台设备"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他设备"</string>
diff --git a/packages/CredentialManager/res/values-zh-rHK/strings.xml b/packages/CredentialManager/res/values-zh-rHK/strings.xml
index 0014d7d..b8d5fc56 100644
--- a/packages/CredentialManager/res/values-zh-rHK/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rHK/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"其他密碼管理工具"</string>
     <string name="close_sheet" msgid="1393792015338908262">"閂工作表"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一頁"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"關閉"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密鑰嗎?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資料嗎?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已鎖定的密碼管理工具"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"輕按即可解鎖"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"沒有登入資料"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中沒有登入資料"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登入資料"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"透過其他裝置"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他裝置"</string>
diff --git a/packages/CredentialManager/res/values-zh-rTW/strings.xml b/packages/CredentialManager/res/values-zh-rTW/strings.xml
index 6173584..885753a 100644
--- a/packages/CredentialManager/res/values-zh-rTW/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rTW/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"其他密碼管理工具"</string>
     <string name="close_sheet" msgid="1393792015338908262">"關閉功能表"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"返回上一頁"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"關閉"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」密碼金鑰嗎?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"要使用已儲存的「<xliff:g id="APP_NAME">%1$s</xliff:g>」登入資訊嗎?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"已鎖定的密碼管理工具"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"輕觸即可解鎖"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"沒有登入資訊"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"<xliff:g id="SOURCE">%1$s</xliff:g> 中沒有登入資訊"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"管理登入資訊"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"透過其他裝置"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"使用其他裝置"</string>
diff --git a/packages/CredentialManager/res/values-zu/strings.xml b/packages/CredentialManager/res/values-zu/strings.xml
index a1c3230..f077d57 100644
--- a/packages/CredentialManager/res/values-zu/strings.xml
+++ b/packages/CredentialManager/res/values-zu/strings.xml
@@ -47,7 +47,8 @@
     <string name="other_password_manager" msgid="565790221427004141">"Abanye abaphathi bephasiwedi"</string>
     <string name="close_sheet" msgid="1393792015338908262">"Vala ishidi"</string>
     <string name="accessibility_back_arrow_button" msgid="3233198183497842492">"Buyela emuva ekhasini langaphambilini"</string>
-    <!-- no translation found for accessibility_close_button (1163435587545377687) -->
+    <string name="accessibility_close_button" msgid="1163435587545377687">"Vala"</string>
+    <!-- no translation found for accessibility_snackbar_dismiss (3456598374801836120) -->
     <skip />
     <string name="get_dialog_title_use_passkey_for" msgid="6236608872708021767">"Sebenzisa ukhiye wakho wokungena olondoloziwe <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
     <string name="get_dialog_title_use_sign_in_for" msgid="5283099528915572980">"Sebenzisa ukungena kwakho ngemvume okulondoloziwe <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
@@ -60,8 +61,7 @@
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Abaphathi bephasiwedi abakhiyiwe"</string>
     <string name="locked_credential_entry_label_subtext_tap_to_unlock" msgid="6390367581393605009">"Thepha ukuze uvule"</string>
     <string name="locked_credential_entry_label_subtext_no_sign_in" msgid="8131725029983174901">"Alukho ulwazi lokungena ngemvume"</string>
-    <!-- no translation found for no_sign_in_info_in (2641118151920288356) -->
-    <skip />
+    <string name="no_sign_in_info_in" msgid="2641118151920288356">"Alukho ulwazi lokungena ngemvume lwe-<xliff:g id="SOURCE">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_manage_sign_ins" msgid="3522556476480676782">"Phatha ukungena ngemvume"</string>
     <string name="get_dialog_heading_from_another_device" msgid="1166697017046724072">"Kusukela kwenye idivayisi"</string>
     <string name="get_dialog_option_headline_use_a_different_device" msgid="8201578814988047549">"Sebenzisa idivayisi ehlukile"</string>
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index 3eb58f1..ee51242 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -94,6 +94,8 @@
   <string name="accessibility_back_arrow_button">"Go back to the previous page"</string>
   <!-- Spoken content description of the close "X" icon button. -->
   <string name="accessibility_close_button">Close</string>
+  <!-- Spoken content description of the close "X" icon button. [CHAR LIMIT=NONE] -->
+  <string name="accessibility_snackbar_dismiss">Dismiss</string>
 
   <!-- Strings for the get flow. -->
   <!-- This appears as the title of the modal bottom sheet asking for user confirmation to use the single previously saved passkey to sign in to the app. [CHAR LIMIT=200] -->
diff --git a/packages/CredentialManager/res/values/themes.xml b/packages/CredentialManager/res/values/themes.xml
index a58a038..c7e4796 100644
--- a/packages/CredentialManager/res/values/themes.xml
+++ b/packages/CredentialManager/res/values/themes.xml
@@ -1,13 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-
   <style name="Theme.CredentialSelector" parent="@android:style/ThemeOverlay.Material">
-    <item name="android:statusBarColor">@android:color/transparent</item>
     <item name="android:windowContentOverlay">@null</item>
     <item name="android:windowNoTitle">true</item>
     <item name="android:windowBackground">@android:color/transparent</item>
     <item name="android:windowIsTranslucent">true</item>
-    <item name="android:colorBackgroundCacheHint">@null</item>
-    <item name="fontFamily">google-sans</item>
+    <item name="android:statusBarColor">@android:color/transparent</item>
+    <item name="android:navigationBarColor">@android:color/transparent</item>
   </style>
 </resources>
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
index 30b97bf..0e604ce 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt
@@ -16,8 +16,6 @@
 
 package com.android.credentialmanager
 
-import android.app.slice.Slice
-import android.app.slice.SliceSpec
 import android.content.Context
 import android.content.Intent
 import android.credentials.CreateCredentialRequest
@@ -25,6 +23,7 @@
 import android.credentials.CredentialOption
 import android.credentials.GetCredentialRequest
 import android.credentials.ui.AuthenticationEntry
+import android.credentials.ui.CancelUiRequest
 import android.credentials.ui.Constants
 import android.credentials.ui.Entry
 import android.credentials.ui.CreateCredentialProviderData
@@ -35,7 +34,6 @@
 import android.credentials.ui.BaseDialogResult
 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
@@ -47,6 +45,8 @@
 import androidx.credentials.CreateCredentialRequest.DisplayInfo
 import androidx.credentials.CreatePublicKeyCredentialRequest
 import androidx.credentials.CreatePasswordRequest
+import androidx.credentials.GetPasswordOption
+import androidx.credentials.GetPublicKeyCredentialOption
 
 import java.time.Instant
 
@@ -73,7 +73,13 @@
         requestInfo = intent.extras?.getParcelable(
             RequestInfo.EXTRA_REQUEST_INFO,
             RequestInfo::class.java
-        ) ?: testCreatePasswordRequestInfo()
+        ) ?: testCreatePasskeyRequestInfo()
+
+        val originName: String? = when (requestInfo.type) {
+            RequestInfo.TYPE_CREATE -> requestInfo.createCredentialRequest?.origin
+            RequestInfo.TYPE_GET -> requestInfo.getCredentialRequest?.origin
+            else -> null
+        }
 
         providerEnabledList = when (requestInfo.type) {
             RequestInfo.TYPE_CREATE ->
@@ -108,15 +114,15 @@
                 val isPasskeyFirstUse = userConfigRepo.getIsPasskeyFirstUse()
                 val providerEnableListUiState = getCreateProviderEnableListInitialUiState()
                 val providerDisableListUiState = getCreateProviderDisableListInitialUiState()
-                val requestDisplayInfoUiState = getCreateRequestDisplayInfoInitialUiState()!!
+                val requestDisplayInfoUiState =
+                    getCreateRequestDisplayInfoInitialUiState(originName)!!
                 UiState(
                     createCredentialUiState = CreateFlowUtils.toCreateCredentialUiState(
                         providerEnableListUiState,
                         providerDisableListUiState,
                         defaultProviderId,
                         requestDisplayInfoUiState,
-                        /** isOnPasskeyIntroStateAlready = */
-                        false,
+                        isOnPasskeyIntroStateAlready = false,
                         isPasskeyFirstUse
                     )!!,
                     getCredentialUiState = null,
@@ -124,7 +130,7 @@
             }
             RequestInfo.TYPE_GET -> UiState(
                 createCredentialUiState = null,
-                getCredentialUiState = getCredentialInitialUiState()!!,
+                getCredentialUiState = getCredentialInitialUiState(originName)!!,
             )
             else -> throw IllegalStateException("Unrecognized request type: ${requestInfo.type}")
         }
@@ -175,11 +181,11 @@
     }
 
     // IMPORTANT: new invocation should be mindful that this method can throw.
-    private fun getCredentialInitialUiState(): GetCredentialUiState? {
+    private fun getCredentialInitialUiState(originName: String?): GetCredentialUiState? {
         val providerEnabledList = GetFlowUtils.toProviderList(
             providerEnabledList as List<GetCredentialProviderData>, context
         )
-        val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context)
+        val requestDisplayInfo = GetFlowUtils.toRequestDisplayInfo(requestInfo, context, originName)
         return GetCredentialUiState(
             providerEnabledList,
             requestDisplayInfo ?: return null,
@@ -201,8 +207,10 @@
         )
     }
 
-    private fun getCreateRequestDisplayInfoInitialUiState(): RequestDisplayInfo? {
-        return CreateFlowUtils.toRequestDisplayInfo(requestInfo, context)
+    private fun getCreateRequestDisplayInfoInitialUiState(
+        originName: String?
+    ): RequestDisplayInfo? {
+        return CreateFlowUtils.toRequestDisplayInfo(requestInfo, context, originName)
     }
 
     companion object {
@@ -217,6 +225,14 @@
                 resultReceiver.send(cancelCode, resultData)
             }
         }
+
+        /** Return the request token whose UI should be cancelled, or null otherwise. */
+        fun getCancelUiRequestToken(intent: Intent): IBinder? {
+            return intent.extras?.getParcelable(
+                CancelUiRequest.EXTRA_CANCEL_UI_REQUEST,
+                CancelUiRequest::class.java
+            )?.token
+        }
     }
 
     // TODO: below are prototype functionalities. To be removed for productionization.
@@ -230,7 +246,8 @@
                             context,
                             "key1", "subkey-1", "elisa.beckett@gmail.com",
                             20, 7, 27, Instant.ofEpochSecond(10L),
-                            "Legal note"
+                            "You can use your passkey on this or other devices. It is saved to " +
+                                "the Password Manager for elisa.beckett@gmail.com."
                         ),
                         CreateTestUtils.newCreateEntry(
                             context,
@@ -239,11 +256,9 @@
                             null
                         ),
                     )
-                )
-                .setRemoteEntry(
-                    newRemoteEntry("key2", "subkey-1")
-                )
-                .build(),
+                ).setRemoteEntry(
+                    CreateTestUtils.newRemoteCreateEntry(context, "key2", "subkey-1")
+                ).build(),
             CreateCredentialProviderData
                 .Builder("com.dashlane")
                 .setSaveEntries(
@@ -258,11 +273,11 @@
                             context,
                             "key1", "subkey-4", "elisa.work@dashlane.com",
                             20, 7, 27, Instant.ofEpochSecond(14L),
-                            null
+                            "You can use your passkey on this or other devices. It is saved to " +
+                                "the Password Manager for elisa.work@dashlane.com"
                         ),
                     )
-                )
-                .build(),
+                ).build(),
         )
     }
 
@@ -318,7 +333,7 @@
                         ),
                     )
                 ).setRemoteEntry(
-                    newRemoteEntry("key4", "subkey-1")
+                    GetTestUtils.newRemoteCredentialEntry(context, "key4", "subkey-1")
                 ).build(),
             GetCredentialProviderData.Builder("com.dashlane")
                 .setCredentialEntries(
@@ -333,10 +348,12 @@
                         ),
                     )
                 ).setAuthenticationEntries(
-                     listOf(GetTestUtils.newAuthenticationEntry(
-                         context, "key2", "subkey-1", "foo@email.com",
-                         AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT
-                     ))
+                     listOf(
+                         GetTestUtils.newAuthenticationEntry(
+                             context, "key2", "subkey-1", "foo@email.com",
+                             AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT,
+                         )
+                     )
                 ).setActionChips(
                     listOf(
                         GetTestUtils.newActionEntry(
@@ -348,20 +365,6 @@
         )
     }
 
-
-    private fun newRemoteEntry(
-        key: String,
-        subkey: String,
-    ): Entry {
-        return Entry(
-            key,
-            subkey,
-            Slice.Builder(
-                Uri.EMPTY, SliceSpec("type", 1)
-            ).build()
-        )
-    }
-
     private fun testCreatePasskeyRequestInfo(): RequestInfo {
         val request = CreatePublicKeyCredentialRequest(
             "{\"extensions\": {\n" +
@@ -398,7 +401,8 @@
                 "                   \"authenticatorSelection\": {\n" +
                 "                     \"residentKey\": \"required\",\n" +
                 "                     \"requireResidentKey\": true\n" +
-                "                   }}"
+                "                   }}",
+            preferImmediatelyAvailableCredentials = true,
         )
         val credentialData = request.credentialData
         return RequestInfo.newCreateRequestInfo(
@@ -444,19 +448,28 @@
     }
 
     private fun testGetRequestInfo(): RequestInfo {
+        val passwordOption = GetPasswordOption()
+        val passkeyOption = GetPublicKeyCredentialOption(
+            "json", preferImmediatelyAvailableCredentials = false)
         return RequestInfo.newGetRequestInfo(
             Binder(),
             GetCredentialRequest.Builder(
                 Bundle()
             ).addCredentialOption(
                 CredentialOption(
-                    "androidx.credentials.TYPE_PUBLIC_KEY_CREDENTIAL",
-                    Bundle(),
-                    Bundle(), /*isSystemProviderRequired=*/
-                    false
+                    passwordOption.type,
+                    passwordOption.requestData,
+                    passwordOption.candidateQueryData,
+                    passwordOption.isSystemProviderRequired
                 )
-            )
-                .build(),
+            ).addCredentialOption(
+                CredentialOption(
+                    passkeyOption.type,
+                    passkeyOption.requestData,
+                    passkeyOption.candidateQueryData,
+                    passkeyOption.isSystemProviderRequired
+                )
+            ).build(),
             "com.google.android.youtube"
         )
     }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index d618e74..e8e3974 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -39,7 +39,7 @@
 import com.android.credentialmanager.createflow.hasContentToDisplay
 import com.android.credentialmanager.getflow.GetCredentialScreen
 import com.android.credentialmanager.getflow.hasContentToDisplay
-import com.android.credentialmanager.ui.theme.CredentialSelectorTheme
+import com.android.credentialmanager.ui.theme.PlatformTheme
 
 @ExperimentalMaterialApi
 class CredentialSelectorActivity : ComponentActivity() {
@@ -47,10 +47,16 @@
         super.onCreate(savedInstanceState)
         Log.d(Constants.LOG_TAG, "Creating new CredentialSelectorActivity")
         try {
+            if (CredentialManagerRepo.getCancelUiRequestToken(intent) != null) {
+                Log.d(
+                    Constants.LOG_TAG, "Received UI cancellation intent; cancelling the activity.")
+                this.finish()
+                return
+            }
             val userConfigRepo = UserConfigRepo(this)
             val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
             setContent {
-                CredentialSelectorTheme {
+                PlatformTheme {
                     CredentialManagerBottomSheet(
                         credManRepo,
                         userConfigRepo
@@ -67,10 +73,19 @@
         setIntent(intent)
         Log.d(Constants.LOG_TAG, "Existing activity received new intent")
         try {
-            val userConfigRepo = UserConfigRepo(this)
-            val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
+            val cancelUiRequestToken = CredentialManagerRepo.getCancelUiRequestToken(intent)
             val viewModel: CredentialSelectorViewModel by viewModels()
-            viewModel.onNewCredentialManagerRepo(credManRepo)
+            if (cancelUiRequestToken != null &&
+                viewModel.shouldCancelCurrentUi(cancelUiRequestToken)) {
+                Log.d(
+                    Constants.LOG_TAG, "Received UI cancellation intent; cancelling the activity.")
+                this.finish()
+                return
+            } else {
+                val userConfigRepo = UserConfigRepo(this)
+                val credManRepo = CredentialManagerRepo(this, intent, userConfigRepo)
+                viewModel.onNewCredentialManagerRepo(credManRepo)
+            }
         } catch (e: Exception) {
             onInitializationError(e, intent)
         }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index a1e0823..9b7139c 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -17,6 +17,7 @@
 package com.android.credentialmanager
 
 import android.app.Activity
+import android.os.IBinder
 import android.util.Log
 import androidx.activity.compose.ManagedActivityResultLauncher
 import androidx.activity.result.ActivityResult
@@ -135,6 +136,11 @@
         uiState = uiState.copy(dialogState = DialogState.COMPLETE)
     }
 
+    /** Return true if the current UI's request token matches the UI cancellation request token. */
+    fun shouldCancelCurrentUi(cancelRequestToken: IBinder): Boolean {
+        return credManRepo.requestInfo.token.equals(cancelRequestToken)
+    }
+
     /**************************************************************************/
     /*****                      Get Flow Callbacks                        *****/
     /**************************************************************************/
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
index aa0959c..a834994 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt
@@ -50,7 +50,11 @@
 import androidx.credentials.CreateCredentialRequest
 import androidx.credentials.CreateCustomCredentialRequest
 import androidx.credentials.CreatePasswordRequest
+import androidx.credentials.CredentialOption
 import androidx.credentials.CreatePublicKeyCredentialRequest
+import androidx.credentials.CreatePublicKeyCredentialRequestPrivileged
+import androidx.credentials.GetPublicKeyCredentialOption
+import androidx.credentials.GetPublicKeyCredentialOptionPrivileged
 import androidx.credentials.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL
 import androidx.credentials.provider.Action
 import androidx.credentials.provider.AuthenticationAction
@@ -170,10 +174,29 @@
         fun toRequestDisplayInfo(
             requestInfo: RequestInfo,
             context: Context,
+            originName: String?,
         ): com.android.credentialmanager.getflow.RequestDisplayInfo? {
+            val getCredentialRequest = requestInfo.getCredentialRequest ?: return null
+            val preferImmediatelyAvailableCredentials = getCredentialRequest.credentialOptions.any {
+                val credentialOptionJetpack = CredentialOption.createFrom(
+                    it.type,
+                    it.credentialRetrievalData,
+                    it.credentialRetrievalData,
+                    it.isSystemProviderRequired
+                )
+                if (credentialOptionJetpack is GetPublicKeyCredentialOption) {
+                    credentialOptionJetpack.preferImmediatelyAvailableCredentials
+                } else if (credentialOptionJetpack is GetPublicKeyCredentialOptionPrivileged) {
+                    credentialOptionJetpack.preferImmediatelyAvailableCredentials
+                } else {
+                    false
+                }
+            }
             return com.android.credentialmanager.getflow.RequestDisplayInfo(
-                appName = getAppLabel(context.packageManager, requestInfo.appPackageName)
-                    ?: return null
+                appName = originName
+                    ?: getAppLabel(context.packageManager, requestInfo.appPackageName)
+                    ?: return null,
+                preferImmediatelyAvailableCredentials = preferImmediatelyAvailableCredentials
             )
         }
 
@@ -287,6 +310,7 @@
                     pendingIntent = structuredAuthEntry.pendingIntent,
                     fillInIntent = entry.frameworkExtrasIntent,
                     title = title,
+                    providerDisplayName = providerDisplayName,
                     icon = providerIcon,
                     isUnlockedAndEmpty = entry.status != AuthenticationEntry.STATUS_LOCKED,
                     isLastUnlocked =
@@ -394,8 +418,10 @@
         fun toRequestDisplayInfo(
             requestInfo: RequestInfo,
             context: Context,
+            originName: String?,
         ): RequestDisplayInfo? {
-            val appLabel = getAppLabel(context.packageManager, requestInfo.appPackageName)
+            val appLabel = originName
+                ?: getAppLabel(context.packageManager, requestInfo.appPackageName)
                 ?: return null
             val createCredentialRequest = requestInfo.createCredentialRequest ?: return null
             val createCredentialRequestJetpack = CreateCredentialRequest.createFrom(
@@ -410,24 +436,25 @@
                     createCredentialRequestJetpack.password,
                     CredentialType.PASSWORD,
                     appLabel,
-                    context.getDrawable(R.drawable.ic_password)!!
+                    context.getDrawable(R.drawable.ic_password) ?: return null,
+                    preferImmediatelyAvailableCredentials = false,
                 )
                 is CreatePublicKeyCredentialRequest -> {
-                    val requestJson = createCredentialRequestJetpack.requestJson
-                    val json = JSONObject(requestJson)
-                    var name = ""
-                    var displayName = ""
-                    if (json.has("user")) {
-                        val user: JSONObject = json.getJSONObject("user")
-                        name = user.getString("name")
-                        displayName = user.getString("displayName")
-                    }
-                    RequestDisplayInfo(
-                        name,
-                        displayName,
-                        CredentialType.PASSKEY,
-                        appLabel,
-                        context.getDrawable(R.drawable.ic_passkey)!!
+                    newRequestDisplayInfoFromPasskeyJson(
+                        requestJson = createCredentialRequestJetpack.requestJson,
+                        appLabel = appLabel,
+                        context = context,
+                        preferImmediatelyAvailableCredentials =
+                        createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
+                    )
+                }
+                is CreatePublicKeyCredentialRequestPrivileged -> {
+                    newRequestDisplayInfoFromPasskeyJson(
+                        requestJson = createCredentialRequestJetpack.requestJson,
+                        appLabel = appLabel,
+                        context = context,
+                        preferImmediatelyAvailableCredentials =
+                        createCredentialRequestJetpack.preferImmediatelyAvailableCredentials,
                     )
                 }
                 is CreateCustomCredentialRequest -> {
@@ -441,7 +468,8 @@
                         type = CredentialType.UNKNOWN,
                         appName = appLabel,
                         typeIcon = displayInfo.credentialTypeIcon?.loadDrawable(context)
-                            ?: context.getDrawable(R.drawable.ic_other_sign_in)!!
+                            ?: context.getDrawable(R.drawable.ic_other_sign_in) ?: return null,
+                        preferImmediatelyAvailableCredentials = false,
                     )
                 }
                 else -> null
@@ -608,5 +636,29 @@
                 )
             } else null
         }
+
+        private fun newRequestDisplayInfoFromPasskeyJson(
+            requestJson: String,
+            appLabel: String,
+            context: Context,
+            preferImmediatelyAvailableCredentials: Boolean,
+        ): RequestDisplayInfo? {
+            val json = JSONObject(requestJson)
+            var name = ""
+            var displayName = ""
+            if (json.has("user")) {
+                val user: JSONObject = json.getJSONObject("user")
+                name = user.getString("name")
+                displayName = user.getString("displayName")
+            }
+            return RequestDisplayInfo(
+                name,
+                displayName,
+                CredentialType.PASSKEY,
+                appLabel,
+                context.getDrawable(R.drawable.ic_passkey) ?: return null,
+                preferImmediatelyAvailableCredentials,
+            )
+        }
     }
 }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt b/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
index eb3d188..9216429 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/TestUtils.kt
@@ -29,6 +29,8 @@
 import androidx.credentials.provider.CreateEntry
 import androidx.credentials.provider.PasswordCredentialEntry
 import androidx.credentials.provider.PublicKeyCredentialEntry
+import androidx.credentials.provider.RemoteCreateEntry
+import androidx.credentials.provider.RemoteCredentialEntry
 
 import java.time.Instant
 
@@ -69,6 +71,21 @@
             )
         }
 
+        internal fun newRemoteCredentialEntry(
+            context: Context,
+            key: String,
+            subkey: String,
+        ): Entry {
+            val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
+            val pendingIntent =
+                PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
+            return Entry(
+                key,
+                subkey,
+                RemoteCredentialEntry(pendingIntent).slice
+            )
+        }
+
         internal fun newActionEntry(
             context: Context,
             key: String,
@@ -203,5 +220,20 @@
                 Intent()
             )
         }
+
+        internal fun newRemoteCreateEntry(
+            context: Context,
+            key: String,
+            subkey: String,
+        ): Entry {
+            val intent = Intent(Settings.ACTION_SYNC_SETTINGS)
+            val pendingIntent =
+                PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
+            return Entry(
+                key,
+                subkey,
+                RemoteCreateEntry(pendingIntent).slice
+            )
+        }
     }
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt
index 6d07df7..2971433 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/DialogResult.kt
@@ -24,8 +24,6 @@
 
 enum class ResultState {
   COMPLETE,
-  NORMAL_CANCELED,
-  LAUNCH_SETTING_CANCELED
 }
 
 data class DialogResult(
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 58edb25..335d58a 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/material/ModalBottomSheet.kt
@@ -451,7 +451,7 @@
 }
 
 @Composable
-private fun Scrim(
+internal fun Scrim(
     color: Color,
     onDismiss: () -> Unit,
     visible: Boolean
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 984057a..04a2c07 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ActionButton.kt
@@ -16,6 +16,8 @@
 
 package com.android.credentialmanager.common.ui
 
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.padding
 import com.android.credentialmanager.R
 import androidx.compose.material.Icon
 import androidx.compose.material.IconButton
@@ -24,7 +26,6 @@
 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
@@ -32,17 +33,19 @@
 import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
-import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
+import androidx.compose.ui.unit.dp
 
 @Composable
 fun ActionButton(text: String, onClick: () -> Unit) {
     TextButton(
+        modifier = Modifier.padding(vertical = 4.dp),
         onClick = onClick,
         colors = ButtonDefaults.textButtonColors(
             contentColor = MaterialTheme.colorScheme.primary,
-        )
+        ),
+        contentPadding = PaddingValues(start = 12.dp, top = 10.dp, end = 12.dp, bottom = 10.dp),
     ) {
-        Text(text = text)
+        LargeLabelText(text = text)
     }
 }
 
@@ -64,7 +67,7 @@
             contentDescription = if (toggleState.value)
                 stringResource(R.string.content_description_show_password) else
                 stringResource(R.string.content_description_hide_password),
-            tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant
+            tint = MaterialTheme.colorScheme.onSurfaceVariant,
         )
     }
 }
\ 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 85e5c1e..cc73089 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Cards.kt
@@ -16,33 +16,77 @@
 
 package com.android.credentialmanager.common.ui
 
-import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.LazyListScope
 import androidx.compose.material3.Card
 import androidx.compose.material3.CardDefaults
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Shape
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
 
 /**
- * By default the card is filled with surfaceVariant color. This container card instead fills the
- * background color with surface corlor.
+ * Container card for the whole sheet.
+ *
+ * Surface 1 color. No vertical padding. 24dp horizontal padding. 24dp bottom padding. 24dp top
+ * padding if [topAppBar] is not present, and none otherwise.
  */
 @Composable
-fun ContainerCard(
+fun SheetContainerCard(
+    topAppBar: (@Composable () -> Unit)? = null,
     modifier: Modifier = Modifier,
-    shape: Shape = CardDefaults.shape,
-    border: BorderStroke? = null,
+    contentVerticalArrangement: Arrangement.Vertical = Arrangement.Top,
+    content: LazyListScope.() -> Unit,
+) {
+    Card(
+        modifier = modifier.fillMaxWidth().wrapContentHeight(),
+        border = null,
+        colors = CardDefaults.cardColors(
+            containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
+                ElevationTokens.Level1
+            ),
+        ),
+    ) {
+        if (topAppBar != null) {
+            topAppBar()
+        }
+        LazyColumn(
+            modifier = Modifier.padding(
+                start = 24.dp,
+                end = 24.dp,
+                bottom = 18.dp,
+                top = if (topAppBar == null) 24.dp else 0.dp
+            ).fillMaxWidth().wrapContentHeight(),
+            horizontalAlignment = Alignment.CenterHorizontally,
+            content = content,
+            verticalArrangement = contentVerticalArrangement,
+        )
+    }
+}
+
+/**
+ * Container card for the entries.
+ *
+ * Surface 3 color. No padding. Four rounded corner shape.
+ */
+@Composable
+fun CredentialContainerCard(
+    modifier: Modifier = Modifier,
     content: @Composable ColumnScope.() -> Unit,
 ) {
     Card(
-        modifier = modifier.fillMaxWidth(),
-        shape = shape,
-        border = border,
+        modifier = modifier.fillMaxWidth().wrapContentHeight(),
+        shape = MaterialTheme.shapes.medium,
+        border = null,
         colors = CardDefaults.cardColors(
-            containerColor = MaterialTheme.colorScheme.surface,
+            containerColor = Color.Transparent,
         ),
         content = content,
     )
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ColorScheme.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ColorScheme.kt
new file mode 100644
index 0000000..b2489fd
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ColorScheme.kt
@@ -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.credentialmanager.common.ui
+
+import androidx.compose.material3.ColorScheme
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.compositeOver
+import androidx.compose.ui.unit.Dp
+import androidx.compose.ui.unit.dp
+import kotlin.math.ln
+
+fun ColorScheme.surfaceColorAtElevation(elevation: Dp): Color {
+    if (elevation == 0.dp) return surface
+    val alpha = ((4.5f * ln(elevation.value + 1)) + 2f) / 100f
+    return surfaceTint.copy(alpha = alpha).compositeOver(surface)
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
index d8ee750..c09a692 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ConfirmButton.kt
@@ -16,21 +16,27 @@
 
 package com.android.credentialmanager.common.ui
 
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.padding
 import androidx.compose.material3.ButtonDefaults
 import androidx.compose.material3.FilledTonalButton
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.unit.dp
 
+/**  Primary container color; label-large button text; on-primary button text color. */
 @Composable
 fun ConfirmButton(text: String, onClick: () -> Unit) {
     FilledTonalButton(
+        modifier = Modifier.padding(vertical = 4.dp),
         onClick = onClick,
         colors = ButtonDefaults.filledTonalButtonColors(
-            containerColor = MaterialTheme.colorScheme.primaryContainer,
-            contentColor = MaterialTheme.colorScheme.onPrimaryContainer,
-        )
+            containerColor = MaterialTheme.colorScheme.primary,
+            contentColor = MaterialTheme.colorScheme.onPrimary,
+        ),
+        contentPadding = PaddingValues(start = 24.dp, top = 10.dp, end = 24.dp, bottom = 10.dp),
     ) {
-        Text(text = text)
+        LargeLabelText(text = text)
     }
 }
\ No newline at end of file
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ElevationTokens.kt
similarity index 65%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to packages/CredentialManager/src/com/android/credentialmanager/common/ui/ElevationTokens.kt
index 35d5c15..e1e666e 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/ElevationTokens.kt
@@ -14,6 +14,16 @@
  * limitations under the License.
  */
 
-package android.net.wifi.sharedconnectivity.app;
+package com.android.credentialmanager.common.ui
 
-parcelable DeviceInfo;
\ No newline at end of file
+import androidx.compose.ui.unit.dp
+
+/** Copied from androidx.compose.material3.tokens. */
+internal object ElevationTokens {
+    val Level0 = 0.0.dp
+    val Level1 = 1.0.dp
+    val Level2 = 3.0.dp
+    val Level3 = 6.0.dp
+    val Level4 = 8.0.dp
+    val Level5 = 12.0.dp
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
index aefd534..bffa40e 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Entry.kt
@@ -16,55 +16,314 @@
 
 package com.android.credentialmanager.common.ui
 
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ArrowBack
+import androidx.compose.material.icons.outlined.Lock
 import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.SuggestionChip
 import androidx.compose.material3.SuggestionChipDefaults
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
 import androidx.compose.runtime.Composable
+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.ImageBitmap
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.input.PasswordVisualTransformation
+import androidx.compose.ui.unit.dp
+import com.android.credentialmanager.R
 import com.android.credentialmanager.ui.theme.EntryShape
+import com.android.credentialmanager.ui.theme.Shapes
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun Entry(
-    onClick: () -> Unit,
-    label: @Composable () -> Unit,
     modifier: Modifier = Modifier,
-    icon: @Composable (() -> Unit)? = null,
+    onClick: () -> Unit,
+    entryHeadlineText: String,
+    entrySecondLineText: String? = null,
+    entryThirdLineText: String? = null,
+    /** Supply one and only one of the [iconImageBitmap], [iconImageVector], or [iconPainter] for
+     *  drawing the leading icon. */
+    iconImageBitmap: ImageBitmap? = null,
+    shouldApplyIconImageBitmapTint: Boolean = false,
+    iconImageVector: ImageVector? = null,
+    iconPainter: Painter? = null,
+    /** This will replace the [entrySecondLineText] value and render the text along with a
+     *  mask on / off toggle for hiding / displaying the password value. */
+    passwordValue: String? = null,
+    /** If true, draws a trailing lock icon. */
+    isLockedAuthEntry: Boolean = false,
 ) {
     SuggestionChip(
-        modifier = modifier.fillMaxWidth(),
+        modifier = modifier.fillMaxWidth().wrapContentHeight(),
         onClick = onClick,
         shape = EntryShape.FullSmallRoundedCorner,
-        label = label,
-        icon = icon,
+        label = {
+            Row(
+                horizontalArrangement = Arrangement.SpaceBetween,
+                modifier = Modifier.fillMaxWidth().padding(all = 16.dp),
+                verticalAlignment = Alignment.CenterVertically,
+            ) {
+                Column(modifier = Modifier.wrapContentSize()) {
+                    SmallTitleText(entryHeadlineText)
+                    if (passwordValue != null) {
+                        Row(modifier = Modifier.fillMaxWidth()) {
+                            val visualTransformation = remember { PasswordVisualTransformation() }
+                            val originalPassword by remember {
+                                mutableStateOf(passwordValue)
+                            }
+                            val displayedPassword = remember {
+                                mutableStateOf(
+                                    visualTransformation.filter(
+                                        AnnotatedString(originalPassword)
+                                    ).text.text
+                                )
+                            }
+                            BodySmallText(displayedPassword.value)
+                            ToggleVisibilityButton(
+                                modifier = Modifier.padding(start = 5.dp).size(24.dp),
+                                onToggle = {
+                                    if (it) {
+                                        displayedPassword.value = originalPassword
+                                    } else {
+                                        displayedPassword.value = visualTransformation.filter(
+                                            AnnotatedString(originalPassword)
+                                        ).text.text
+                                    }
+                                },
+                            )
+                        }
+                    } else if (entrySecondLineText != null) {
+                        BodySmallText(entrySecondLineText)
+                    }
+                    if (entryThirdLineText != null) {
+                        BodySmallText(entryThirdLineText)
+                    }
+                }
+                if (isLockedAuthEntry) {
+                    Box(modifier = Modifier.wrapContentSize().padding(end = 16.dp)) {
+                        Icon(
+                            imageVector = Icons.Outlined.Lock,
+                            // Decorative purpose only.
+                            contentDescription = null,
+                            modifier = Modifier.size(24.dp),
+                            tint = MaterialTheme.colorScheme.onSurfaceVariant,
+                        )
+                    }
+                }
+            }
+        },
+        icon =
+        if (iconImageBitmap != null) {
+            if (shouldApplyIconImageBitmapTint) {
+                {
+                    Box(modifier = Modifier.wrapContentSize()
+                        .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+                        Icon(
+                            modifier = Modifier.size(24.dp),
+                            bitmap = iconImageBitmap,
+                            tint = MaterialTheme.colorScheme.onSurfaceVariant,
+                            // Decorative purpose only.
+                            contentDescription = null,
+                        )
+                    }
+                }
+            } else {
+                {
+                    Box(modifier = Modifier.wrapContentSize()
+                        .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+                        Image(
+                            modifier = Modifier.size(24.dp),
+                            bitmap = iconImageBitmap,
+                            // Decorative purpose only.
+                            contentDescription = null,
+                        )
+                    }
+                }
+            }
+        } else if (iconImageVector != null) {
+            {
+                Box(modifier = Modifier.wrapContentSize()
+                    .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+                    Icon(
+                        modifier = Modifier.size(24.dp),
+                        imageVector = iconImageVector,
+                        tint = MaterialTheme.colorScheme.onSurfaceVariant,
+                        // Decorative purpose only.
+                        contentDescription = null,
+                    )
+                }
+            }
+        } else if (iconPainter != null) {
+            {
+                Box(modifier = Modifier.wrapContentSize()
+                    .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+                    Icon(
+                        modifier = Modifier.size(24.dp),
+                        painter = iconPainter,
+                        tint = MaterialTheme.colorScheme.onSurfaceVariant,
+                        // Decorative purpose only.
+                        contentDescription = null,
+                    )
+                }
+            }
+        } else {
+            null
+        },
         border = null,
         colors = SuggestionChipDefaults.suggestionChipColors(
-            containerColor = MaterialTheme.colorScheme.surfaceVariant,
+            containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(
+                ElevationTokens.Level3
+            ),
+            // TODO: remove?
             labelColor = MaterialTheme.colorScheme.onSurfaceVariant,
             iconContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
         ),
     )
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
+/**
+ * A variation of the normal entry in that its background is transparent and the paddings are
+ * different (no horizontal padding).
+ */
 @Composable
-fun TransparentBackgroundEntry(
+fun ActionEntry(
     onClick: () -> Unit,
-    label: @Composable () -> Unit,
-    modifier: Modifier = Modifier,
-    icon: @Composable (() -> Unit)? = null,
+    entryHeadlineText: String,
+    entrySecondLineText: String? = null,
+    iconImageBitmap: ImageBitmap,
 ) {
     SuggestionChip(
-        modifier = modifier.fillMaxWidth(),
+        modifier = Modifier.fillMaxWidth().wrapContentHeight(),
         onClick = onClick,
-        label = label,
-        icon = icon,
+        shape = Shapes.large,
+        label = {
+            Column(modifier = Modifier.wrapContentSize()
+                .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)) {
+                SmallTitleText(entryHeadlineText)
+                if (entrySecondLineText != null) {
+                    BodySmallText(entrySecondLineText)
+                }
+            }
+        },
+        icon = {
+            Box(modifier = Modifier.wrapContentSize().padding(vertical = 16.dp)) {
+                Image(
+                    modifier = Modifier.size(24.dp),
+                    bitmap = iconImageBitmap,
+                    // Decorative purpose only.
+                    contentDescription = null,
+                )
+            }
+        },
         border = null,
         colors = SuggestionChipDefaults.suggestionChipColors(
             containerColor = Color.Transparent,
         ),
     )
+}
+
+/**
+ * A single row of leading icon and text describing a benefit of passkeys, used by the
+ * [com.android.credentialmanager.createflow.PasskeyIntroCard].
+ */
+@Composable
+fun PasskeyBenefitRow(
+    leadingIconPainter: Painter,
+    text: String,
+) {
+    Row(
+        horizontalArrangement = Arrangement.spacedBy(16.dp),
+        verticalAlignment = Alignment.CenterVertically,
+        modifier = Modifier.fillMaxWidth()
+    ) {
+        Icon(
+            modifier = Modifier.size(24.dp),
+            painter = leadingIconPainter,
+            tint = MaterialTheme.colorScheme.onSurfaceVariant,
+            // Decorative purpose only.
+            contentDescription = null,
+        )
+        BodyMediumText(text = text)
+    }
+}
+
+/**
+ * A single row of one or two CTA buttons for continuing or cancelling the current step.
+ */
+@Composable
+fun CtaButtonRow(
+    leftButton: (@Composable () -> Unit)? = null,
+    rightButton: (@Composable () -> Unit)? = null,
+) {
+    Row(
+        horizontalArrangement =
+        if (leftButton == null) Arrangement.End
+        else if (rightButton == null) Arrangement.Start
+        else Arrangement.SpaceBetween,
+        verticalAlignment = Alignment.CenterVertically,
+        modifier = Modifier.fillMaxWidth()
+    ) {
+        if (leftButton != null) {
+            leftButton()
+        }
+        if (rightButton != null) {
+            rightButton()
+        }
+    }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun MoreOptionTopAppBar(
+    text: String,
+    onNavigationIconClicked: () -> Unit,
+) {
+    TopAppBar(
+        title = {
+            LargeTitleText(text = text, modifier = Modifier.padding(horizontal = 4.dp))
+        },
+        navigationIcon = {
+            IconButton(
+                modifier = Modifier.padding(top = 8.dp, bottom = 8.dp, start = 4.dp).size(48.dp),
+                onClick = onNavigationIconClicked
+            ) {
+                Box(
+                    modifier = Modifier.size(48.dp),
+                    contentAlignment = Alignment.Center,
+                ) {
+                    Icon(
+                        imageVector = Icons.Filled.ArrowBack,
+                        contentDescription = stringResource(
+                            R.string.accessibility_back_arrow_button
+                        ),
+                        modifier = Modifier.size(16.dp),
+                        tint = MaterialTheme.colorScheme.onSurfaceVariant,
+                    )
+                }
+            }
+        },
+        colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
+        modifier = Modifier.padding(top = 12.dp, bottom = 8.dp)
+    )
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/HeadlineIcon.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/HeadlineIcon.kt
new file mode 100644
index 0000000..ac79844
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/HeadlineIcon.kt
@@ -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.credentialmanager.common.ui
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ImageBitmap
+import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.unit.dp
+
+/** Tinted primary; centered; 32X32. */
+@Composable
+fun HeadlineIcon(bitmap: ImageBitmap, tint: Color? = null) {
+    Row(
+        horizontalArrangement = Arrangement.Center,
+        modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+    ) {
+        Icon(
+            modifier = Modifier.size(32.dp),
+            bitmap = bitmap,
+            tint = tint ?: MaterialTheme.colorScheme.primary,
+            // Decorative purpose only.
+            contentDescription = null,
+        )
+    }
+}
+
+@Composable
+fun HeadlineIcon(imageVector: ImageVector) {
+    Row(
+        horizontalArrangement = Arrangement.Center,
+        modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+    ) {
+        Icon(
+            modifier = Modifier.size(32.dp),
+            imageVector = imageVector,
+            tint = MaterialTheme.colorScheme.primary,
+            // Decorative purpose only.
+            contentDescription = null,
+        )
+    }
+}
+
+@Composable
+fun HeadlineIcon(painter: Painter) {
+    Row(
+        horizontalArrangement = Arrangement.Center,
+        modifier = Modifier.fillMaxWidth().wrapContentHeight(),
+    ) {
+        Icon(
+            modifier = Modifier.size(32.dp),
+            painter = painter,
+            tint = MaterialTheme.colorScheme.primary,
+            // Decorative purpose only.
+            contentDescription = null,
+        )
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt
new file mode 100644
index 0000000..c63771e
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SectionHeader.kt
@@ -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.credentialmanager.common.ui
+
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun CredentialListSectionHeader(text: String) {
+    InternalSectionHeader(text, MaterialTheme.colorScheme.onSurfaceVariant)
+}
+
+@Composable
+fun MoreAboutPasskeySectionHeader(text: String) {
+    InternalSectionHeader(text, MaterialTheme.colorScheme.onSurface)
+}
+
+@Composable
+private fun InternalSectionHeader(text: String, color: Color) {
+    Row(modifier = Modifier.fillMaxWidth().wrapContentHeight()) {
+        SectionHeaderText(
+            text,
+            modifier = Modifier.padding(top = 20.dp, bottom = 8.dp),
+            color = color
+        )
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.kt
new file mode 100644
index 0000000..514ff90
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/SnackBar.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.credentialmanager.common.ui
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxWithConstraints
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentSize
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import com.android.credentialmanager.R
+import com.android.credentialmanager.common.material.Scrim
+import com.android.credentialmanager.ui.theme.Shapes
+
+@Composable
+fun Snackbar(
+    contentText: String,
+    action: (@Composable () -> Unit)? = null,
+    onDismiss: () -> Unit,
+) {
+    BoxWithConstraints {
+        Box(Modifier.fillMaxSize()) {
+            Scrim(
+                color = Color.Transparent,
+                onDismiss = onDismiss,
+                visible = true
+            )
+        }
+        Box(
+            modifier = Modifier
+                .align(Alignment.BottomCenter).wrapContentSize().padding(bottom = 18.dp)
+        ) {
+            Card(
+                shape = Shapes.medium,
+                modifier = Modifier.wrapContentSize(),
+                colors = CardDefaults.cardColors(
+                    containerColor = MaterialTheme.colorScheme.inverseSurface,
+                )
+            ) {
+                Row(
+                    modifier = Modifier.wrapContentSize(),
+                    verticalAlignment = Alignment.CenterVertically,
+                ) {
+                    SnackbarContentText(contentText, modifier = Modifier.padding(
+                        top = 18.dp, bottom = 18.dp, start = 24.dp,
+                    ))
+                    if (action != null) {
+                        action()
+                    }
+                    IconButton(onClick = onDismiss, modifier = Modifier.padding(
+                        top = 4.dp, bottom = 4.dp, start = 2.dp, end = 10.dp,
+                    )) {
+                        Icon(
+                            Icons.Filled.Close,
+                            contentDescription = stringResource(
+                                R.string.accessibility_snackbar_dismiss
+                            ),
+                            tint = MaterialTheme.colorScheme.inverseOnSurface,
+                        )
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
index 3a66dda..8af729e 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/ui/Texts.kt
@@ -16,69 +16,144 @@
 
 package com.android.credentialmanager.common.ui
 
+import androidx.compose.foundation.layout.wrapContentSize
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.style.TextAlign
 
+/**
+ * The headline for a screen. E.g. "Create a passkey for X", "Choose a saved sign-in for X".
+ *
+ * Centered horizontally; headline-small typography; on-surface color.
+ */
 @Composable
-fun TextOnSurface(
-    text: String,
-    modifier: Modifier = Modifier,
-    textAlign: TextAlign? = null,
-    style: TextStyle,
-) {
-    TextInternal(
+fun HeadlineText(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
         text = text,
         color = MaterialTheme.colorScheme.onSurface,
-        modifier = modifier,
-        textAlign = textAlign,
-        style = style,
+        textAlign = TextAlign.Center,
+        style = MaterialTheme.typography.headlineSmall,
     )
 }
 
+/**
+ * Body-medium typography; on-surface-variant color.
+ */
 @Composable
-fun TextSecondary(
-    text: String,
-    modifier: Modifier = Modifier,
-    textAlign: TextAlign? = null,
-    style: TextStyle,
-) {
-    TextInternal(
-        text = text,
-        color = MaterialTheme.colorScheme.secondary,
-        modifier = modifier,
-        textAlign = textAlign,
-        style = style,
-    )
-}
-
-@Composable
-fun TextOnSurfaceVariant(
-    text: String,
-    modifier: Modifier = Modifier,
-    textAlign: TextAlign? = null,
-    style: TextStyle,
-) {
-    TextInternal(
+fun BodyMediumText(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
         text = text,
         color = MaterialTheme.colorScheme.onSurfaceVariant,
-        modifier = modifier,
-        textAlign = textAlign,
-        style = style,
+        style = MaterialTheme.typography.bodyMedium,
     )
 }
 
+/**
+ * Body-small typography; on-surface-variant color.
+ */
 @Composable
-private fun TextInternal(
-    text: String,
-    color: Color,
-    modifier: Modifier,
-    textAlign: TextAlign?,
-    style: TextStyle,
-) {
-    Text(text = text, color = color, modifier = modifier, textAlign = textAlign, style = style)
+fun BodySmallText(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        color = MaterialTheme.colorScheme.onSurfaceVariant,
+        style = MaterialTheme.typography.bodySmall,
+    )
+}
+
+/**
+ * Title-large typography; on-surface color.
+ */
+@Composable
+fun LargeTitleText(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        color = MaterialTheme.colorScheme.onSurface,
+        style = MaterialTheme.typography.titleLarge,
+    )
+}
+
+/**
+ * Title-small typography; on-surface color.
+ */
+@Composable
+fun SmallTitleText(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        color = MaterialTheme.colorScheme.onSurface,
+        style = MaterialTheme.typography.titleSmall,
+    )
+}
+
+/**
+ * Title-small typography.
+ */
+@Composable
+fun SectionHeaderText(text: String, modifier: Modifier = Modifier, color: Color) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        color = color,
+        style = MaterialTheme.typography.titleSmall,
+    )
+}
+
+/**
+ * Body-medium typography; inverse-on-surface color.
+ */
+@Composable
+fun SnackbarContentText(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        color = MaterialTheme.colorScheme.inverseOnSurface,
+        style = MaterialTheme.typography.bodyMedium,
+    )
+}
+
+/**
+ * Label-large typography; inverse-primary color.
+ */
+@Composable
+fun SnackbarActionText(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        color = MaterialTheme.colorScheme.inversePrimary,
+        style = MaterialTheme.typography.labelLarge,
+    )
+}
+
+/**
+ * Label-large typography; on-surface-variant color; centered.
+ */
+@Composable
+fun LargeLabelTextOnSurfaceVariant(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        textAlign = TextAlign.Center,
+        color = MaterialTheme.colorScheme.onSurfaceVariant,
+        style = MaterialTheme.typography.labelLarge,
+    )
+}
+
+/**
+ * Label-large typography; color following parent spec; centered.
+ */
+@Composable
+fun LargeLabelText(text: String, modifier: Modifier = Modifier) {
+    Text(
+        modifier = modifier.wrapContentSize(),
+        text = text,
+        textAlign = TextAlign.Center,
+        style = MaterialTheme.typography.labelLarge,
+    )
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index 942eb49..00b7d00 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -11,36 +11,24 @@
 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
+import androidx.compose.foundation.layout.wrapContentHeight
 import androidx.compose.material3.Divider
 import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.TopAppBar
-import androidx.compose.material3.TopAppBarDefaults
 import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.ArrowBack
 import androidx.compose.material.icons.outlined.NewReleases
 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
@@ -49,15 +37,20 @@
 import com.android.credentialmanager.common.CredentialType
 import com.android.credentialmanager.common.ProviderActivityState
 import com.android.credentialmanager.common.ui.ActionButton
+import com.android.credentialmanager.common.ui.BodyMediumText
+import com.android.credentialmanager.common.ui.BodySmallText
 import com.android.credentialmanager.common.ui.ConfirmButton
+import com.android.credentialmanager.common.ui.CredentialContainerCard
+import com.android.credentialmanager.common.ui.CtaButtonRow
 import com.android.credentialmanager.common.ui.Entry
+import com.android.credentialmanager.common.ui.HeadlineIcon
+import com.android.credentialmanager.common.ui.LargeLabelTextOnSurfaceVariant
 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.ToggleVisibilityButton
-import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
+import com.android.credentialmanager.common.ui.MoreAboutPasskeySectionHeader
+import com.android.credentialmanager.common.ui.MoreOptionTopAppBar
+import com.android.credentialmanager.common.ui.SheetContainerCard
+import com.android.credentialmanager.common.ui.PasskeyBenefitRow
+import com.android.credentialmanager.common.ui.HeadlineText
 
 @Composable
 fun CreateCredentialScreen(
@@ -73,7 +66,7 @@
             when (viewModel.uiState.providerActivityState) {
                 ProviderActivityState.NOT_APPLICABLE -> {
                     when (createCredentialUiState.currentScreenState) {
-                        CreateScreenState.PASSKEY_INTRO -> ConfirmationCard(
+                        CreateScreenState.PASSKEY_INTRO -> PasskeyIntroCard(
                             onConfirm = viewModel::createFlowOnConfirmIntro,
                             onLearnMore = viewModel::createFlowOnLearnMore,
                         )
@@ -157,14 +150,13 @@
     )
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
-fun ConfirmationCard(
+fun PasskeyIntroCard(
     onConfirm: () -> Unit,
     onLearnMore: () -> Unit,
 ) {
-    ContainerCard() {
-        Column() {
+    SheetContainerCard {
+        item {
             val onboardingImageResource = remember {
                 mutableStateOf(R.drawable.ic_passkeys_onboarding)
             }
@@ -173,101 +165,56 @@
             } else {
                 onboardingImageResource.value = R.drawable.ic_passkeys_onboarding
             }
-            Image(
-                painter = painterResource(onboardingImageResource.value),
-                contentDescription = null,
-                modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
-                    .padding(top = 24.dp, bottom = 12.dp).size(316.dp, 168.dp)
-            )
-            TextOnSurface(
-                text = stringResource(R.string.passkey_creation_intro_title),
-                style = MaterialTheme.typography.titleMedium,
-                modifier = Modifier
-                    .padding(horizontal = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally),
-                textAlign = TextAlign.Center,
-            )
-            Divider(
-                thickness = 16.dp,
-                color = Color.Transparent
-            )
             Row(
-                horizontalArrangement = Arrangement.SpaceBetween,
-                verticalAlignment = Alignment.CenterVertically,
-                modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
+                modifier = Modifier.wrapContentHeight().fillMaxWidth(),
+                horizontalArrangement = Arrangement.Center,
             ) {
                 Image(
-                    modifier = Modifier.size(24.dp),
-                    painter = painterResource(R.drawable.ic_passkeys_onboarding_password),
-                    contentDescription = null
-                )
-                TextSecondary(
-                    text = stringResource(R.string.passkey_creation_intro_body_password),
-                    style = MaterialTheme.typography.bodyMedium,
-                    modifier = Modifier.padding(start = 16.dp, end = 4.dp),
+                    painter = painterResource(onboardingImageResource.value),
+                    contentDescription = null,
+                    modifier = Modifier.size(316.dp, 168.dp)
                 )
             }
-            Divider(
-                thickness = 16.dp,
-                color = Color.Transparent
+        }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item { HeadlineText(text = stringResource(R.string.passkey_creation_intro_title)) }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            PasskeyBenefitRow(
+                leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_password),
+                text = stringResource(R.string.passkey_creation_intro_body_password),
             )
-            Row(
-                horizontalArrangement = Arrangement.SpaceBetween,
-                verticalAlignment = Alignment.CenterVertically,
-                modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
-            ) {
-                Image(
-                    modifier = Modifier.size(24.dp),
-                    painter = painterResource(R.drawable.ic_passkeys_onboarding_fingerprint),
-                    contentDescription = null
-                )
-                TextSecondary(
-                    text = stringResource(R.string.passkey_creation_intro_body_fingerprint),
-                    style = MaterialTheme.typography.bodyMedium,
-                    modifier = Modifier.padding(start = 16.dp, end = 4.dp),
-                )
-            }
-            Divider(
-                thickness = 16.dp,
-                color = Color.Transparent
+        }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            PasskeyBenefitRow(
+                leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_fingerprint),
+                text = stringResource(R.string.passkey_creation_intro_body_fingerprint),
             )
-            Row(
-                horizontalArrangement = Arrangement.SpaceBetween,
-                verticalAlignment = Alignment.CenterVertically,
-                modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
-            ) {
-                Image(
-                    modifier = Modifier.size(24.dp),
-                    painter = painterResource(R.drawable.ic_passkeys_onboarding_device),
-                    contentDescription = null
-                )
-                TextSecondary(
-                    text = stringResource(R.string.passkey_creation_intro_body_device),
-                    style = MaterialTheme.typography.bodyMedium,
-                    modifier = Modifier.padding(start = 16.dp, end = 4.dp),
-                )
-            }
-            Divider(
-                thickness = 32.dp,
-                color = Color.Transparent
+        }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            PasskeyBenefitRow(
+                leadingIconPainter = painterResource(R.drawable.ic_passkeys_onboarding_device),
+                text = stringResource(R.string.passkey_creation_intro_body_device),
             )
-            Row(
-                horizontalArrangement = Arrangement.SpaceBetween,
-                modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
-            ) {
-                ActionButton(
-                    stringResource(R.string.string_learn_more),
-                    onClick = onLearnMore
-                )
-                ConfirmButton(
-                    stringResource(R.string.string_continue),
-                    onClick = onConfirm
-                )
-            }
-            Divider(
-                thickness = 18.dp,
-                color = Color.Transparent,
-                modifier = Modifier.padding(bottom = 18.dp)
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+
+        item {
+            CtaButtonRow(
+                leftButton = {
+                    ActionButton(
+                        stringResource(R.string.string_learn_more),
+                        onClick = onLearnMore
+                    )
+                },
+                rightButton = {
+                    ConfirmButton(
+                        stringResource(R.string.string_continue),
+                        onClick = onConfirm
+                    )
+                },
             )
         }
     }
@@ -283,16 +230,11 @@
     onDisabledProvidersSelected: () -> Unit,
     onMoreOptionsSelected: () -> Unit,
 ) {
-    ContainerCard() {
-        Column() {
-            Icon(
-                bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap(),
-                contentDescription = null,
-                tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
-                modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
-                    .padding(top = 24.dp, bottom = 16.dp).size(32.dp)
-            )
-            TextOnSurface(
+    SheetContainerCard {
+        item { HeadlineIcon(bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap()) }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            HeadlineText(
                 text = stringResource(
                     R.string.choose_provider_title,
                     when (requestDisplayInfo.type) {
@@ -302,83 +244,56 @@
                             stringResource(R.string.passwords)
                         CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
                     }
-                ),
-                style = MaterialTheme.typography.titleMedium,
-                modifier = Modifier.padding(horizontal = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally),
-                textAlign = TextAlign.Center,
+                )
             )
-            Divider(
-                thickness = 16.dp,
-                color = Color.Transparent
-            )
-            TextSecondary(
-                text = stringResource(R.string.choose_provider_body),
-                style = MaterialTheme.typography.bodyLarge,
-                modifier = Modifier.padding(horizontal = 28.dp),
-            )
-            ContainerCard(
-                shape = MaterialTheme.shapes.medium,
-                modifier = Modifier.padding(
-                    start = 24.dp,
-                    end = 24.dp,
-                    top = 24.dp,
-                    bottom = if (hasRemoteEntry) 24.dp else 16.dp
-                ).align(alignment = Alignment.CenterHorizontally),
-            ) {
-                LazyColumn(
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+
+        item { BodyMediumText(text = stringResource(R.string.choose_provider_body)) }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            CredentialContainerCard {
+                Column(
                     verticalArrangement = Arrangement.spacedBy(2.dp)
                 ) {
                     sortedCreateOptionsPairs.forEach { entry ->
-                        item {
-                            MoreOptionsInfoRow(
-                                requestDisplayInfo = requestDisplayInfo,
-                                providerInfo = entry.second,
-                                createOptionInfo = entry.first,
-                                onOptionSelected = {
-                                    onOptionSelected(
-                                        ActiveEntry(
-                                            entry.second,
-                                            entry.first
-                                        )
+                        MoreOptionsInfoRow(
+                            requestDisplayInfo = requestDisplayInfo,
+                            providerInfo = entry.second,
+                            createOptionInfo = entry.first,
+                            onOptionSelected = {
+                                onOptionSelected(
+                                    ActiveEntry(
+                                        entry.second,
+                                        entry.first
                                     )
-                                }
-                            )
-                        }
-                    }
-                    item {
-                        MoreOptionsDisabledProvidersRow(
-                            disabledProviders = disabledProviderList,
-                            onDisabledProvidersSelected =
-                            onDisabledProvidersSelected,
+                                )
+                            }
                         )
                     }
-                }
-            }
-            if (hasRemoteEntry) {
-                Divider(
-                    thickness = 24.dp,
-                    color = Color.Transparent
-                )
-                Row(
-                    horizontalArrangement = Arrangement.Start,
-                    modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
-                ) {
-                    ActionButton(
-                        stringResource(R.string.string_more_options),
-                        onMoreOptionsSelected
+                    MoreOptionsDisabledProvidersRow(
+                        disabledProviders = disabledProviderList,
+                        onDisabledProvidersSelected = onDisabledProvidersSelected,
                     )
                 }
             }
-            Divider(
-                thickness = 24.dp,
-                color = Color.Transparent,
-            )
+        }
+        if (hasRemoteEntry) {
+            item { Divider(thickness = 24.dp, color = Color.Transparent) }
+            item {
+                CtaButtonRow(
+                    leftButton = {
+                        ActionButton(
+                            stringResource(R.string.string_more_options),
+                            onMoreOptionsSelected
+                        )
+                    }
+                )
+            }
         }
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun MoreOptionsSelectionCard(
     requestDisplayInfo: RequestDisplayInfo,
@@ -393,158 +308,104 @@
     onDisabledProvidersSelected: () -> Unit,
     onRemoteEntrySelected: (BaseEntry) -> Unit,
 ) {
-    ContainerCard() {
-        Column() {
-            TopAppBar(
-                title = {
-                    TextOnSurface(
-                        text =
-                        stringResource(
-                            R.string.save_credential_to_title,
-                            when (requestDisplayInfo.type) {
-                                CredentialType.PASSKEY ->
-                                    stringResource(R.string.passkey)
-                                CredentialType.PASSWORD ->
-                                    stringResource(R.string.password)
-                                CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
-                            }
-                        ),
-                        style = MaterialTheme.typography.titleMedium,
-                    )
-                },
-                navigationIcon = {
-                    IconButton(
-                        onClick =
-                        if (isFromProviderSelection)
-                            onBackProviderSelectionButtonSelected
-                        else onBackCreationSelectionButtonSelected
-                    ) {
-                        Icon(
-                            Icons.Filled.ArrowBack,
-                            stringResource(R.string.accessibility_back_arrow_button)
-                        )
-                    }
-                },
-                colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
-                modifier = Modifier.padding(top = 12.dp)
-            )
-            Divider(
-                thickness = 8.dp,
-                color = Color.Transparent
-            )
-            ContainerCard(
-                shape = MaterialTheme.shapes.medium,
-                modifier = Modifier
-                    .padding(horizontal = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally)
-            ) {
-                LazyColumn(
-                    verticalArrangement = Arrangement.spacedBy(2.dp)
-                ) {
+    SheetContainerCard(topAppBar = {
+        MoreOptionTopAppBar(
+            text = stringResource(
+                R.string.save_credential_to_title,
+                when (requestDisplayInfo.type) {
+                    CredentialType.PASSKEY ->
+                        stringResource(R.string.passkey)
+                    CredentialType.PASSWORD ->
+                        stringResource(R.string.password)
+                    CredentialType.UNKNOWN -> stringResource(R.string.sign_in_info)
+                }
+            ),
+            onNavigationIconClicked =
+            if (isFromProviderSelection) onBackProviderSelectionButtonSelected
+            else onBackCreationSelectionButtonSelected,
+        )
+    }) {
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            CredentialContainerCard {
+                Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
                     // Only in the flows with default provider(not first time use) we can show the
                     // createOptions here, or they will be shown on ProviderSelectionCard
                     if (hasDefaultProvider) {
                         sortedCreateOptionsPairs.forEach { entry ->
-                            item {
-                                MoreOptionsInfoRow(
-                                    requestDisplayInfo = requestDisplayInfo,
-                                    providerInfo = entry.second,
-                                    createOptionInfo = entry.first,
-                                    onOptionSelected = {
-                                        onOptionSelected(
-                                            ActiveEntry(
-                                                entry.second,
-                                                entry.first
-                                            )
+                            MoreOptionsInfoRow(
+                                requestDisplayInfo = requestDisplayInfo,
+                                providerInfo = entry.second,
+                                createOptionInfo = entry.first,
+                                onOptionSelected = {
+                                    onOptionSelected(
+                                        ActiveEntry(
+                                            entry.second,
+                                            entry.first
                                         )
-                                    })
-                            }
-                        }
-                        item {
-                            MoreOptionsDisabledProvidersRow(
-                                disabledProviders = disabledProviderList,
-                                onDisabledProvidersSelected =
-                                onDisabledProvidersSelected,
+                                    )
+                                }
                             )
                         }
+                        MoreOptionsDisabledProvidersRow(
+                            disabledProviders = disabledProviderList,
+                            onDisabledProvidersSelected =
+                            onDisabledProvidersSelected,
+                        )
                     }
                     enabledProviderList.forEach {
                         if (it.remoteEntry != null) {
-                            item {
-                                RemoteEntryRow(
-                                    remoteInfo = it.remoteEntry!!,
-                                    onRemoteEntrySelected = onRemoteEntrySelected,
-                                )
-                            }
+                            RemoteEntryRow(
+                                remoteInfo = it.remoteEntry!!,
+                                onRemoteEntrySelected = onRemoteEntrySelected,
+                            )
                             return@forEach
                         }
                     }
                 }
             }
-            Divider(
-                thickness = 8.dp,
-                color = Color.Transparent,
-                modifier = Modifier.padding(bottom = 40.dp)
-            )
         }
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun MoreOptionsRowIntroCard(
     providerInfo: EnabledProviderInfo,
     onChangeDefaultSelected: () -> Unit,
     onUseOnceSelected: () -> Unit,
 ) {
-    ContainerCard() {
-        Column() {
-            Icon(
-                Icons.Outlined.NewReleases,
-                contentDescription = null,
-                modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
-                    .padding(all = 24.dp),
-                tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
-            )
-            TextOnSurface(
+    SheetContainerCard {
+        item { HeadlineIcon(imageVector = Icons.Outlined.NewReleases) }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            HeadlineText(
                 text = stringResource(
                     R.string.use_provider_for_all_title,
                     providerInfo.displayName
-                ),
-                style = MaterialTheme.typography.titleMedium,
-                modifier = Modifier.padding(horizontal = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally),
-                textAlign = TextAlign.Center,
-            )
-            TextSecondary(
-                text = stringResource(R.string.use_provider_for_all_description),
-                style = MaterialTheme.typography.bodyLarge,
-                modifier = Modifier.padding(all = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally),
-            )
-            Row(
-                horizontalArrangement = Arrangement.SpaceBetween,
-                modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
-            ) {
-                ActionButton(
-                    stringResource(R.string.use_once),
-                    onClick = onUseOnceSelected
                 )
-                ConfirmButton(
-                    stringResource(R.string.set_as_default),
-                    onClick = onChangeDefaultSelected
-                )
-            }
-            Divider(
-                thickness = 18.dp,
-                color = Color.Transparent,
-                modifier = Modifier.padding(bottom = 40.dp)
+            )
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item { BodyMediumText(text = stringResource(R.string.use_provider_for_all_description)) }
+        item {
+            CtaButtonRow(
+                leftButton = {
+                    ActionButton(
+                        stringResource(R.string.use_once),
+                        onClick = onUseOnceSelected
+                    )
+                },
+                rightButton = {
+                    ConfirmButton(
+                        stringResource(R.string.set_as_default),
+                        onClick = onChangeDefaultSelected
+                    )
+                },
             )
         }
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun CreationSelectionCard(
     requestDisplayInfo: RequestDisplayInfo,
@@ -556,26 +417,18 @@
     onMoreOptionsSelected: () -> Unit,
     hasDefaultProvider: Boolean,
 ) {
-    ContainerCard() {
-        Column() {
-            Divider(
-                thickness = 24.dp,
-                color = Color.Transparent
-            )
-            Icon(
+    SheetContainerCard {
+        item {
+            HeadlineIcon(
                 bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
-                contentDescription = null,
                 tint = Color.Unspecified,
-                modifier = Modifier.align(alignment = Alignment.CenterHorizontally).size(32.dp)
             )
-            TextSecondary(
-                text = providerInfo.displayName,
-                style = MaterialTheme.typography.titleLarge,
-                modifier = Modifier.padding(vertical = 10.dp)
-                    .align(alignment = Alignment.CenterHorizontally),
-                textAlign = TextAlign.Center,
-            )
-            TextOnSurface(
+        }
+        item { Divider(thickness = 4.dp, color = Color.Transparent) }
+        item { LargeLabelTextOnSurfaceVariant(text = providerInfo.displayName) }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item {
+            HeadlineText(
                 text = when (requestDisplayInfo.type) {
                     CredentialType.PASSKEY -> stringResource(
                         R.string.choose_create_option_passkey_title,
@@ -589,80 +442,67 @@
                         R.string.choose_create_option_sign_in_title,
                         requestDisplayInfo.appName
                     )
-                },
-                style = MaterialTheme.typography.titleMedium,
-                modifier = Modifier.padding(horizontal = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally),
-                textAlign = TextAlign.Center,
+                }
             )
-            ContainerCard(
-                shape = MaterialTheme.shapes.medium,
-                modifier = Modifier
-                    .padding(all = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally),
-            ) {
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            CredentialContainerCard {
                 PrimaryCreateOptionRow(
                     requestDisplayInfo = requestDisplayInfo,
                     entryInfo = createOptionInfo,
                     onOptionSelected = onOptionSelected
                 )
             }
-            var createOptionsSize = 0
-            var remoteEntry: RemoteInfo? = null
-            enabledProviderList.forEach { enabledProvider ->
-                if (enabledProvider.remoteEntry != null) {
-                    remoteEntry = enabledProvider.remoteEntry
-                }
-                createOptionsSize += enabledProvider.createOptions.size
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        var createOptionsSize = 0
+        var remoteEntry: RemoteInfo? = null
+        enabledProviderList.forEach { enabledProvider ->
+            if (enabledProvider.remoteEntry != null) {
+                remoteEntry = enabledProvider.remoteEntry
             }
-            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 =
-                if (shouldShowMoreOptionsButton) Arrangement.SpaceBetween else Arrangement.End,
-                modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
-            ) {
-                if (shouldShowMoreOptionsButton) {
-                    ActionButton(
-                        stringResource(R.string.string_more_options),
-                        onClick = onMoreOptionsSelected
+            createOptionsSize += enabledProvider.createOptions.size
+        }
+        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
+        }
+        item {
+            CtaButtonRow(
+                leftButton = if (shouldShowMoreOptionsButton) {
+                    {
+                        ActionButton(
+                            stringResource(R.string.string_more_options),
+                            onMoreOptionsSelected
+                        )
+                    }
+                } else null,
+                rightButton = {
+                    ConfirmButton(
+                        stringResource(R.string.string_continue),
+                        onClick = onConfirm
                     )
-                }
-                ConfirmButton(
-                    stringResource(R.string.string_continue),
-                    onClick = onConfirm
-                )
-            }
-            if (createOptionInfo.footerDescription != null) {
+                },
+            )
+        }
+        if (createOptionInfo.footerDescription != null) {
+            item {
                 Divider(
                     thickness = 1.dp,
-                    color = Color.LightGray,
-                    modifier = Modifier.padding(start = 24.dp, end = 24.dp, top = 18.dp)
-                )
-                TextSecondary(
-                    text = createOptionInfo.footerDescription,
-                    style = MaterialTheme.typography.bodyLarge,
-                    modifier = Modifier.padding(
-                        start = 29.dp, top = 8.dp, bottom = 18.dp, end = 28.dp
-                    )
+                    color = MaterialTheme.colorScheme.outlineVariant,
+                    modifier = Modifier.padding(vertical = 16.dp)
                 )
             }
-            Divider(
-                thickness = 18.dp,
-                color = Color.Transparent,
-                modifier = Modifier.padding(bottom = 16.dp)
-            )
+            item { BodySmallText(text = createOptionInfo.footerDescription) }
         }
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun ExternalOnlySelectionCard(
     requestDisplayInfo: RequestDisplayInfo,
@@ -670,148 +510,74 @@
     onOptionSelected: (BaseEntry) -> Unit,
     onConfirm: () -> Unit,
 ) {
-    ContainerCard() {
-        Column() {
-            Icon(
-                painter = painterResource(R.drawable.ic_other_devices),
-                contentDescription = null,
-                tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
-                modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
-                    .padding(all = 24.dp).size(32.dp)
-            )
-            TextOnSurface(
-                text = stringResource(R.string.create_passkey_in_other_device_title),
-                style = MaterialTheme.typography.titleMedium,
-                modifier = Modifier.padding(horizontal = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally),
-                textAlign = TextAlign.Center,
-            )
-            Divider(
-                thickness = 24.dp,
-                color = Color.Transparent
-            )
-            ContainerCard(
-                shape = MaterialTheme.shapes.medium,
-                modifier = Modifier
-                    .padding(horizontal = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally),
-            ) {
+    SheetContainerCard {
+        item { HeadlineIcon(painter = painterResource(R.drawable.ic_other_devices)) }
+        item { Divider(thickness = 16.dp, color = Color.Transparent) }
+        item { HeadlineText(text = stringResource(R.string.create_passkey_in_other_device_title)) }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            CredentialContainerCard {
                 PrimaryCreateOptionRow(
                     requestDisplayInfo = requestDisplayInfo,
                     entryInfo = activeRemoteEntry,
                     onOptionSelected = onOptionSelected
                 )
             }
-            Divider(
-                thickness = 24.dp,
-                color = Color.Transparent
-            )
-            Row(
-                horizontalArrangement = Arrangement.End,
-                modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
-            ) {
-                ConfirmButton(
-                    stringResource(R.string.string_continue),
-                    onClick = onConfirm
-                )
-            }
-            Divider(
-                thickness = 18.dp,
-                color = Color.Transparent,
-                modifier = Modifier.padding(bottom = 16.dp)
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            CtaButtonRow(
+                rightButton = {
+                    ConfirmButton(
+                        stringResource(R.string.string_continue),
+                        onClick = onConfirm
+                    )
+                },
             )
         }
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun MoreAboutPasskeysIntroCard(
     onBackPasskeyIntroButtonSelected: () -> Unit,
 ) {
-    ContainerCard() {
-        Column() {
-            TopAppBar(
-                title = {
-                    TextOnSurface(
-                        text =
-                        stringResource(
-                            R.string.more_about_passkeys_title
-                        ),
-                        style = MaterialTheme.typography.titleMedium,
-                    )
-                },
-                navigationIcon = {
-                    IconButton(
-                        onClick = onBackPasskeyIntroButtonSelected
-                    ) {
-                        Icon(
-                            Icons.Filled.ArrowBack,
-                            stringResource(R.string.accessibility_back_arrow_button)
-                        )
-                    }
-                },
-                colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
-                modifier = Modifier.padding(top = 12.dp)
+    SheetContainerCard(
+        topAppBar = {
+            MoreOptionTopAppBar(
+                text = stringResource(R.string.more_about_passkeys_title),
+                onNavigationIconClicked = onBackPasskeyIntroButtonSelected,
             )
-            Column(
-                modifier = Modifier.fillMaxWidth().padding(start = 24.dp, end = 68.dp)
-            ) {
-                TextOnSurfaceVariant(
-                    text = stringResource(R.string.passwordless_technology_title),
-                    style = MaterialTheme.typography.titleLarge,
-                )
-                TextSecondary(
-                    text = stringResource(R.string.passwordless_technology_detail),
-                    style = MaterialTheme.typography.bodyMedium,
-                )
-                Divider(
-                    thickness = 24.dp,
-                    color = Color.Transparent
-                )
-                TextOnSurfaceVariant(
-                    text = stringResource(R.string.public_key_cryptography_title),
-                    style = MaterialTheme.typography.titleLarge,
-                )
-                TextSecondary(
-                    text = stringResource(R.string.public_key_cryptography_detail),
-                    style = MaterialTheme.typography.bodyMedium,
-                )
-                Divider(
-                    thickness = 24.dp,
-                    color = Color.Transparent
-                )
-                TextOnSurfaceVariant(
-                    text = stringResource(R.string.improved_account_security_title),
-                    style = MaterialTheme.typography.titleLarge,
-                )
-                TextSecondary(
-                    text = stringResource(R.string.improved_account_security_detail),
-                    style = MaterialTheme.typography.bodyMedium,
-                )
-                Divider(
-                    thickness = 24.dp,
-                    color = Color.Transparent
-                )
-                TextOnSurfaceVariant(
-                    text = stringResource(R.string.seamless_transition_title),
-                    style = MaterialTheme.typography.titleLarge,
-                )
-                TextSecondary(
-                    text = stringResource(R.string.seamless_transition_detail),
-                    style = MaterialTheme.typography.bodyMedium,
-                )
-            }
-            Divider(
-                thickness = 18.dp,
-                color = Color.Transparent,
-                modifier = Modifier.padding(bottom = 24.dp)
+        },
+        contentVerticalArrangement = Arrangement.spacedBy(8.dp)
+    ) {
+        item {
+            MoreAboutPasskeySectionHeader(
+                text = stringResource(R.string.passwordless_technology_title)
             )
+            BodyMediumText(text = stringResource(R.string.passwordless_technology_detail))
+        }
+        item {
+            MoreAboutPasskeySectionHeader(
+                text = stringResource(R.string.public_key_cryptography_title)
+            )
+            BodyMediumText(text = stringResource(R.string.public_key_cryptography_detail))
+        }
+        item {
+            MoreAboutPasskeySectionHeader(
+                text = stringResource(R.string.improved_account_security_title)
+            )
+            BodyMediumText(text = stringResource(R.string.improved_account_security_detail))
+        }
+        item {
+            MoreAboutPasskeySectionHeader(
+                text = stringResource(R.string.seamless_transition_title)
+            )
+            BodyMediumText(text = stringResource(R.string.seamless_transition_detail))
         }
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun PrimaryCreateOptionRow(
     requestDisplayInfo: RequestDisplayInfo,
@@ -820,115 +586,37 @@
 ) {
     Entry(
         onClick = { onOptionSelected(entryInfo) },
-        icon = {
-            if (entryInfo is CreateOptionInfo && entryInfo.profileIcon != null) {
-                Image(
-                    bitmap = entryInfo.profileIcon.toBitmap().asImageBitmap(),
-                    contentDescription = null,
-                    modifier = Modifier.padding(start = 10.dp).size(32.dp),
-                )
-            } else {
-                Icon(
-                    bitmap = requestDisplayInfo.typeIcon.toBitmap().asImageBitmap(),
-                    contentDescription = null,
-                    tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
-                    modifier = Modifier.padding(start = 10.dp).size(32.dp),
-                )
-            }
+        iconImageBitmap =
+        if (entryInfo is CreateOptionInfo && entryInfo.profileIcon != null) {
+            entryInfo.profileIcon.toBitmap().asImageBitmap()
+        } else {
+            requestDisplayInfo.typeIcon.toBitmap().asImageBitmap()
         },
-        label = {
-            Column() {
-                when (requestDisplayInfo.type) {
-                    CredentialType.PASSKEY -> {
-                        TextOnSurfaceVariant(
-                            text = requestDisplayInfo.title,
-                            style = MaterialTheme.typography.titleLarge,
-                            modifier = Modifier.padding(top = 16.dp, start = 5.dp),
-                        )
-                        TextSecondary(
-                            text = if (requestDisplayInfo.subtitle != null) {
-                                requestDisplayInfo.subtitle + " • " + stringResource(
-                                    R.string.passkey_before_subtitle
-                                )
-                            } else {
-                                stringResource(R.string.passkey_before_subtitle)
-                            },
-                            style = MaterialTheme.typography.bodyMedium,
-                            modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
-                        )
-                    }
-                    CredentialType.PASSWORD -> {
-                        TextOnSurfaceVariant(
-                            text = requestDisplayInfo.title,
-                            style = MaterialTheme.typography.titleLarge,
-                            modifier = Modifier.padding(top = 16.dp, start = 5.dp),
-                        )
-                        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
-                            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
-                                }
-                            })
-                        }
-                    }
-                    CredentialType.UNKNOWN -> {
-                        if (requestDisplayInfo.subtitle != null) {
-                            TextOnSurfaceVariant(
-                                text = requestDisplayInfo.title,
-                                style = MaterialTheme.typography.titleLarge,
-                                modifier = Modifier.padding(top = 16.dp, start = 5.dp),
-                            )
-                            TextOnSurfaceVariant(
-                                text = requestDisplayInfo.subtitle,
-                                style = MaterialTheme.typography.bodyMedium,
-                                modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
-                            )
-                        } else {
-                            TextOnSurfaceVariant(
-                                text = requestDisplayInfo.title,
-                                style = MaterialTheme.typography.titleLarge,
-                                modifier = Modifier.padding(
-                                    top = 16.dp, bottom = 16.dp, start = 5.dp
-                                ),
-                            )
-                        }
-                    }
+        shouldApplyIconImageBitmapTint = !(entryInfo is CreateOptionInfo &&
+            entryInfo.profileIcon != null),
+        entryHeadlineText = requestDisplayInfo.title,
+        entrySecondLineText = when (requestDisplayInfo.type) {
+            CredentialType.PASSKEY -> {
+                if (requestDisplayInfo.subtitle != null) {
+                    requestDisplayInfo.subtitle + " • " + stringResource(
+                        R.string.passkey_before_subtitle
+                    )
+                } else {
+                    stringResource(R.string.passkey_before_subtitle)
                 }
             }
-        }
+            // Set passwordValue instead
+            CredentialType.PASSWORD -> null
+            CredentialType.UNKNOWN -> requestDisplayInfo.subtitle
+        },
+        passwordValue =
+        if (requestDisplayInfo.type == CredentialType.PASSWORD)
+        // This subtitle would never be null for create password
+            requestDisplayInfo.subtitle ?: ""
+        else null,
     )
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun MoreOptionsInfoRow(
     requestDisplayInfo: RequestDisplayInfo,
@@ -938,93 +626,46 @@
 ) {
     Entry(
         onClick = onOptionSelected,
-        icon = {
-            Image(
-                modifier = Modifier.padding(start = 10.dp).size(32.dp),
-                bitmap = providerInfo.icon.toBitmap().asImageBitmap(),
-                contentDescription = null
-            )
-        },
-        label = {
-            Column() {
-                TextOnSurfaceVariant(
-                    text = providerInfo.displayName,
-                    style = MaterialTheme.typography.titleLarge,
-                    modifier = Modifier.padding(top = 16.dp, start = 5.dp),
+        iconImageBitmap = providerInfo.icon.toBitmap().asImageBitmap(),
+        entryHeadlineText = providerInfo.displayName,
+        entrySecondLineText = createOptionInfo.userProviderDisplayName,
+        entryThirdLineText =
+        if (requestDisplayInfo.type == CredentialType.PASSKEY ||
+            requestDisplayInfo.type == CredentialType.PASSWORD) {
+            if (createOptionInfo.passwordCount != null &&
+                createOptionInfo.passkeyCount != null
+            ) {
+                stringResource(
+                    R.string.more_options_usage_passwords_passkeys,
+                    createOptionInfo.passwordCount,
+                    createOptionInfo.passkeyCount
                 )
-                if (createOptionInfo.userProviderDisplayName != null) {
-                    TextSecondary(
-                        text = createOptionInfo.userProviderDisplayName,
-                        style = MaterialTheme.typography.bodyMedium,
-                        modifier = Modifier.padding(start = 5.dp),
-                    )
-                }
-                if (requestDisplayInfo.type == CredentialType.PASSKEY ||
-                    requestDisplayInfo.type == CredentialType.PASSWORD
-                ) {
-                    if (createOptionInfo.passwordCount != null &&
-                        createOptionInfo.passkeyCount != null
-                    ) {
-                        TextSecondary(
-                            text =
-                            stringResource(
-                                R.string.more_options_usage_passwords_passkeys,
-                                createOptionInfo.passwordCount,
-                                createOptionInfo.passkeyCount
-                            ),
-                            style = MaterialTheme.typography.bodyMedium,
-                            modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
-                        )
-                    } else if (createOptionInfo.passwordCount != null) {
-                        TextSecondary(
-                            text =
-                            stringResource(
-                                R.string.more_options_usage_passwords,
-                                createOptionInfo.passwordCount
-                            ),
-                            style = MaterialTheme.typography.bodyMedium,
-                            modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
-                        )
-                    } else if (createOptionInfo.passkeyCount != null) {
-                        TextSecondary(
-                            text =
-                            stringResource(
-                                R.string.more_options_usage_passkeys,
-                                createOptionInfo.passkeyCount
-                            ),
-                            style = MaterialTheme.typography.bodyMedium,
-                            modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
-                        )
-                    } else {
-                        Divider(
-                            thickness = 16.dp,
-                            color = Color.Transparent,
-                        )
-                    }
-                } else {
-                    if (createOptionInfo.totalCredentialCount != null) {
-                        TextSecondary(
-                            text =
-                            stringResource(
-                                R.string.more_options_usage_credentials,
-                                createOptionInfo.totalCredentialCount
-                            ),
-                            style = MaterialTheme.typography.bodyMedium,
-                            modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
-                        )
-                    } else {
-                        Divider(
-                            thickness = 16.dp,
-                            color = Color.Transparent,
-                        )
-                    }
-                }
+            } else if (createOptionInfo.passwordCount != null) {
+                stringResource(
+                    R.string.more_options_usage_passwords,
+                    createOptionInfo.passwordCount
+                )
+            } else if (createOptionInfo.passkeyCount != null) {
+                stringResource(
+                    R.string.more_options_usage_passkeys,
+                    createOptionInfo.passkeyCount
+                )
+            } else {
+                null
             }
-        }
+        } else {
+            if (createOptionInfo.totalCredentialCount != null) {
+                stringResource(
+                    R.string.more_options_usage_credentials,
+                    createOptionInfo.totalCredentialCount
+                )
+            } else {
+                null
+            }
+        },
     )
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun MoreOptionsDisabledProvidersRow(
     disabledProviders: List<ProviderInfo>?,
@@ -1033,36 +674,15 @@
     if (disabledProviders != null && disabledProviders.isNotEmpty()) {
         Entry(
             onClick = onDisabledProvidersSelected,
-            icon = {
-                Icon(
-                    Icons.Filled.Add,
-                    contentDescription = null,
-                    modifier = Modifier.padding(start = 16.dp),
-                    tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
-                )
+            iconImageVector = Icons.Filled.Add,
+            entryHeadlineText = stringResource(R.string.other_password_manager),
+            entrySecondLineText = disabledProviders.joinToString(separator = " • ") {
+                it.displayName
             },
-            label = {
-                Column() {
-                    TextOnSurfaceVariant(
-                        text = stringResource(R.string.other_password_manager),
-                        style = MaterialTheme.typography.titleLarge,
-                        modifier = Modifier.padding(top = 16.dp, start = 5.dp),
-                    )
-                    // TODO: Update the subtitle once design is confirmed
-                    TextSecondary(
-                        text = disabledProviders.joinToString(separator = " • ") {
-                            it.displayName
-                        },
-                        style = MaterialTheme.typography.bodyMedium,
-                        modifier = Modifier.padding(bottom = 16.dp, start = 5.dp),
-                    )
-                }
-            }
         )
     }
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun RemoteEntryRow(
     remoteInfo: RemoteInfo,
@@ -1070,23 +690,7 @@
 ) {
     Entry(
         onClick = { onRemoteEntrySelected(remoteInfo) },
-        icon = {
-            Icon(
-                painter = painterResource(R.drawable.ic_other_devices),
-                contentDescription = null,
-                tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
-                modifier = Modifier.padding(start = 10.dp)
-            )
-        },
-        label = {
-            Column() {
-                TextOnSurfaceVariant(
-                    text = stringResource(R.string.another_device),
-                    style = MaterialTheme.typography.titleLarge,
-                    modifier = Modifier.padding(start = 10.dp, top = 18.dp, bottom = 18.dp)
-                        .align(alignment = Alignment.CenterHorizontally),
-                )
-            }
-        }
+        iconPainter = painterResource(R.drawable.ic_other_devices),
+        entryHeadlineText = stringResource(R.string.another_device),
     )
 }
\ No newline at end of file
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
index ce4e936..192fa15 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateModel.kt
@@ -38,7 +38,9 @@
 )
 
 internal fun hasContentToDisplay(state: CreateCredentialUiState): Boolean {
-    return state.sortedCreateOptionsPairs.isNotEmpty()
+    return state.sortedCreateOptionsPairs.isNotEmpty() ||
+        (!state.requestDisplayInfo.preferImmediatelyAvailableCredentials &&
+            state.remoteEntry != null)
 }
 
 open class ProviderInfo(
@@ -104,6 +106,7 @@
   val type: CredentialType,
   val appName: String,
   val typeIcon: Drawable,
+  val preferImmediatelyAvailableCredentials: Boolean,
 )
 
 /**
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index 5704820..c5028c2 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -20,40 +20,23 @@
 import androidx.activity.compose.ManagedActivityResultLauncher
 import androidx.activity.result.ActivityResult
 import androidx.activity.result.IntentSenderRequest
-
-import androidx.compose.foundation.Image
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.heightIn
 import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.size
 import androidx.compose.foundation.layout.wrapContentHeight
-import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.ArrowBack
-import androidx.compose.material.icons.filled.Close
-import androidx.compose.material.icons.outlined.Lock
 import androidx.compose.material3.Divider
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Snackbar
-import androidx.compose.material3.Text
 import androidx.compose.material3.TextButton
-import androidx.compose.material3.TopAppBar
-import androidx.compose.material3.TopAppBarDefaults
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
-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.style.TextAlign
 import androidx.compose.ui.unit.dp
 import androidx.core.graphics.drawable.toBitmap
 import com.android.credentialmanager.CredentialSelectorViewModel
@@ -62,16 +45,18 @@
 import com.android.credentialmanager.common.CredentialType
 import com.android.credentialmanager.common.ProviderActivityState
 import com.android.credentialmanager.common.ui.ActionButton
+import com.android.credentialmanager.common.ui.ActionEntry
 import com.android.credentialmanager.common.ui.ConfirmButton
+import com.android.credentialmanager.common.ui.CredentialContainerCard
+import com.android.credentialmanager.common.ui.CtaButtonRow
 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.ui.theme.EntryShape
-import com.android.credentialmanager.ui.theme.LocalAndroidColorScheme
+import com.android.credentialmanager.common.ui.MoreOptionTopAppBar
+import com.android.credentialmanager.common.ui.SheetContainerCard
+import com.android.credentialmanager.common.ui.SnackbarActionText
+import com.android.credentialmanager.common.ui.HeadlineText
+import com.android.credentialmanager.common.ui.CredentialListSectionHeader
+import com.android.credentialmanager.common.ui.Snackbar
 
 @Composable
 fun GetCredentialScreen(
@@ -154,12 +139,9 @@
     val sortedUserNameToCredentialEntryList =
         providerDisplayInfo.sortedUserNameToCredentialEntryList
     val authenticationEntryList = providerDisplayInfo.authenticationEntryList
-    ContainerCard() {
-        Column() {
-            TextOnSurface(
-                modifier = Modifier.padding(all = 24.dp),
-                textAlign = TextAlign.Center,
-                style = MaterialTheme.typography.headlineSmall,
+    SheetContainerCard {
+        item {
+            HeadlineText(
                 text = stringResource(
                     if (sortedUserNameToCredentialEntryList
                             .size == 1 && authenticationEntryList.isEmpty()
@@ -178,48 +160,42 @@
                     requestDisplayInfo.appName
                 ),
             )
-
-            ContainerCard(
-                shape = MaterialTheme.shapes.medium,
-                modifier = Modifier
-                    .padding(horizontal = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally)
-            ) {
-                val usernameForCredentialSize = sortedUserNameToCredentialEntryList
-                    .size
-                val authenticationEntrySize = authenticationEntryList.size
-                LazyColumn(
-                    verticalArrangement = Arrangement.spacedBy(2.dp)
-                ) {
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        item {
+            CredentialContainerCard {
+                Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
+                    val usernameForCredentialSize = sortedUserNameToCredentialEntryList.size
+                    val authenticationEntrySize = authenticationEntryList.size
                     // Show max 4 entries in this primary page
                     if (usernameForCredentialSize + authenticationEntrySize <= 4) {
-                        items(sortedUserNameToCredentialEntryList) {
+                        sortedUserNameToCredentialEntryList.forEach {
                             CredentialEntryRow(
                                 credentialEntryInfo = it.sortedCredentialEntryList.first(),
                                 onEntrySelected = onEntrySelected,
                             )
                         }
-                        items(authenticationEntryList) {
+                        authenticationEntryList.forEach {
                             AuthenticationEntryRow(
                                 authenticationEntryInfo = it,
                                 onEntrySelected = onEntrySelected,
                             )
                         }
                     } else if (usernameForCredentialSize < 4) {
-                        items(sortedUserNameToCredentialEntryList) {
+                        sortedUserNameToCredentialEntryList.forEach {
                             CredentialEntryRow(
                                 credentialEntryInfo = it.sortedCredentialEntryList.first(),
                                 onEntrySelected = onEntrySelected,
                             )
                         }
-                        items(authenticationEntryList.take(4 - usernameForCredentialSize)) {
+                        authenticationEntryList.take(4 - usernameForCredentialSize).forEach {
                             AuthenticationEntryRow(
                                 authenticationEntryInfo = it,
                                 onEntrySelected = onEntrySelected,
                             )
                         }
                     } else {
-                        items(sortedUserNameToCredentialEntryList.take(4)) {
+                        sortedUserNameToCredentialEntryList.take(4).forEach {
                             CredentialEntryRow(
                                 credentialEntryInfo = it.sortedCredentialEntryList.first(),
                                 onEntrySelected = onEntrySelected,
@@ -228,49 +204,39 @@
                     }
                 }
             }
-            Divider(
-                thickness = 24.dp,
-                color = Color.Transparent
-            )
-            var totalEntriesCount = sortedUserNameToCredentialEntryList
-                .flatMap { it.sortedCredentialEntryList }.size + authenticationEntryList
-                .size + providerInfoList.flatMap { it.actionEntryList }.size
-            if (providerDisplayInfo.remoteEntry != null) totalEntriesCount += 1
-            // Row horizontalArrangement differs on only one actionButton(should place on most
-            // left)/only one confirmButton(should place on most right)/two buttons exist the same
-            // time(should be one on the left, one on the right)
-            Row(
-                horizontalArrangement =
-                if (totalEntriesCount <= 1 && activeEntry != null) Arrangement.End
-                else if (totalEntriesCount > 1 && activeEntry == null) Arrangement.Start
-                else Arrangement.SpaceBetween,
-                modifier = Modifier.fillMaxWidth().padding(horizontal = 24.dp)
-            ) {
-                if (totalEntriesCount > 1) {
-                    ActionButton(
-                        stringResource(R.string.get_dialog_use_saved_passkey_for),
-                        onMoreOptionSelected
-                    )
-                }
-                // Only one sign-in options exist
-                if (activeEntry != null) {
-                    ConfirmButton(
-                        stringResource(R.string.string_continue),
-                        onClick = onConfirm
-                    )
-                }
-            }
-            Divider(
-                thickness = 18.dp,
-                color = Color.Transparent,
-                modifier = Modifier.padding(bottom = 16.dp)
+        }
+        item { Divider(thickness = 24.dp, color = Color.Transparent) }
+        var totalEntriesCount = sortedUserNameToCredentialEntryList
+            .flatMap { it.sortedCredentialEntryList }.size + authenticationEntryList
+            .size + providerInfoList.flatMap { it.actionEntryList }.size
+        if (providerDisplayInfo.remoteEntry != null) totalEntriesCount += 1
+        // Row horizontalArrangement differs on only one actionButton(should place on most
+        // left)/only one confirmButton(should place on most right)/two buttons exist the same
+        // time(should be one on the left, one on the right)
+        item {
+            CtaButtonRow(
+                leftButton = if (totalEntriesCount > 1) {
+                    {
+                        ActionButton(
+                            stringResource(R.string.get_dialog_use_saved_passkey_for),
+                            onMoreOptionSelected
+                        )
+                    }
+                } else null,
+                rightButton = if (activeEntry != null) { // Only one sign-in options exist
+                    {
+                        ConfirmButton(
+                            stringResource(R.string.string_continue),
+                            onClick = onConfirm
+                        )
+                    }
+                } else null,
             )
         }
     }
 }
 
 /** Draws the secondary credential selection page, where all sign-in options are listed. */
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun AllSignInOptionCard(
     providerInfoList: List<ProviderInfo>,
@@ -283,88 +249,52 @@
     val sortedUserNameToCredentialEntryList =
         providerDisplayInfo.sortedUserNameToCredentialEntryList
     val authenticationEntryList = providerDisplayInfo.authenticationEntryList
-    ContainerCard() {
-        Column() {
-            TopAppBar(
-                colors = TopAppBarDefaults.topAppBarColors(
-                    containerColor = Color.Transparent,
-                ),
-                title = {
-                    TextOnSurface(
-                        text = stringResource(R.string.get_dialog_title_sign_in_options),
-                        style = MaterialTheme.typography.titleMedium
-                    )
-                },
-                navigationIcon = {
-                    IconButton(onClick = if (isNoAccount) onCancel else onBackButtonClicked) {
-                        Icon(
-                            Icons.Filled.ArrowBack,
-                            contentDescription = stringResource(
-                                R.string.accessibility_back_arrow_button)
-                        )
-                    }
-                },
-                modifier = Modifier.padding(top = 12.dp)
+    SheetContainerCard(topAppBar = {
+        MoreOptionTopAppBar(
+            text = stringResource(R.string.get_dialog_title_sign_in_options),
+            onNavigationIconClicked = if (isNoAccount) onCancel else onBackButtonClicked,
+        )
+    }) {
+        // For username
+        items(sortedUserNameToCredentialEntryList) { item ->
+            PerUserNameCredentials(
+                perUserNameCredentialEntryList = item,
+                onEntrySelected = onEntrySelected,
             )
-
-            ContainerCard(
-                shape = MaterialTheme.shapes.large,
-                modifier = Modifier
-                    .padding(start = 24.dp, end = 24.dp, bottom = 24.dp)
-                    .align(alignment = Alignment.CenterHorizontally),
-            ) {
-                LazyColumn(
-                    verticalArrangement = Arrangement.spacedBy(8.dp)
-                ) {
-                    // For username
-                    items(sortedUserNameToCredentialEntryList) { item ->
-                        PerUserNameCredentials(
-                            perUserNameCredentialEntryList = item,
-                            onEntrySelected = onEntrySelected,
-                        )
-                    }
-                    // Locked password manager
-                    if (authenticationEntryList.isNotEmpty()) {
-                        item {
-                            LockedCredentials(
-                                authenticationEntryList = authenticationEntryList,
-                                onEntrySelected = onEntrySelected,
-                            )
-                        }
-                    }
-                    item {
-                        Divider(
-                            thickness = 8.dp,
-                            color = Color.Transparent,
-                        )
-                    }
-                    // From another device
-                    val remoteEntry = providerDisplayInfo.remoteEntry
-                    if (remoteEntry != null) {
-                        item {
-                            RemoteEntryCard(
-                                remoteEntry = remoteEntry,
-                                onEntrySelected = onEntrySelected,
-                            )
-                        }
-                    }
-                    item {
-                        Divider(
-                            thickness = 1.dp,
-                            color = Color.LightGray,
-                            modifier = Modifier.padding(top = 16.dp)
-                        )
-                    }
-                    // Manage sign-ins (action chips)
-                    item {
-                        ActionChips(
-                            providerInfoList = providerInfoList,
-                            onEntrySelected = onEntrySelected
-                        )
-                    }
-                }
+        }
+        // Locked password manager
+        if (authenticationEntryList.isNotEmpty()) {
+            item {
+                LockedCredentials(
+                    authenticationEntryList = authenticationEntryList,
+                    onEntrySelected = onEntrySelected,
+                )
             }
         }
+        // From another device
+        val remoteEntry = providerDisplayInfo.remoteEntry
+        if (remoteEntry != null) {
+            item {
+                RemoteEntryCard(
+                    remoteEntry = remoteEntry,
+                    onEntrySelected = onEntrySelected,
+                )
+            }
+        }
+        item {
+            Divider(
+                thickness = 1.dp,
+                color = Color.LightGray,
+                modifier = Modifier.padding(top = 16.dp)
+            )
+        }
+        // Manage sign-ins (action chips)
+        item {
+            ActionChips(
+                providerInfoList = providerInfoList,
+                onEntrySelected = onEntrySelected
+            )
+        }
     }
 }
 
@@ -381,17 +311,11 @@
         return
     }
 
-    TextSecondary(
-        text = stringResource(R.string.get_dialog_heading_manage_sign_ins),
-        style = MaterialTheme.typography.titleLarge,
-        modifier = Modifier.padding(vertical = 8.dp)
+    CredentialListSectionHeader(
+        text = stringResource(R.string.get_dialog_heading_manage_sign_ins)
     )
-    // TODO: tweak padding.
-    ContainerCard(
-        modifier = Modifier.fillMaxWidth().wrapContentHeight(),
-        shape = MaterialTheme.shapes.medium,
-    ) {
-        Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
+    CredentialContainerCard {
+        Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
             actionChips.forEach {
                 ActionEntryRow(it, onEntrySelected)
             }
@@ -404,38 +328,20 @@
     remoteEntry: RemoteEntryInfo,
     onEntrySelected: (BaseEntry) -> Unit,
 ) {
-    TextSecondary(
-        text = stringResource(R.string.get_dialog_heading_from_another_device),
-        style = MaterialTheme.typography.titleLarge,
-        modifier = Modifier.padding(vertical = 8.dp)
+    CredentialListSectionHeader(
+        text = stringResource(R.string.get_dialog_heading_from_another_device)
     )
-    ContainerCard(
-        modifier = Modifier.fillMaxWidth().wrapContentHeight(),
-        shape = MaterialTheme.shapes.medium,
-    ) {
+    CredentialContainerCard {
         Column(
             modifier = Modifier.fillMaxWidth().wrapContentHeight(),
             verticalArrangement = Arrangement.spacedBy(2.dp),
         ) {
             Entry(
                 onClick = { onEntrySelected(remoteEntry) },
-                icon = {
-                    Icon(
-                        painter = painterResource(R.drawable.ic_other_devices),
-                        contentDescription = null,
-                        tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
-                        modifier = Modifier.padding(start = 10.dp)
-                    )
-                },
-                label = {
-                    TextOnSurfaceVariant(
-                        text = stringResource(
-                            R.string.get_dialog_option_headline_use_a_different_device),
-                        style = MaterialTheme.typography.titleLarge,
-                        modifier = Modifier.padding(start = 10.dp, top = 18.dp, bottom = 18.dp)
-                            .align(alignment = Alignment.CenterHorizontally)
-                    )
-                }
+                iconPainter = painterResource(R.drawable.ic_other_devices),
+                entryHeadlineText = stringResource(
+                    R.string.get_dialog_option_headline_use_a_different_device
+                ),
             )
         }
     }
@@ -446,15 +352,10 @@
     authenticationEntryList: List<AuthenticationEntryInfo>,
     onEntrySelected: (BaseEntry) -> Unit,
 ) {
-    TextSecondary(
-        text = stringResource(R.string.get_dialog_heading_locked_password_managers),
-        style = MaterialTheme.typography.labelLarge,
-        modifier = Modifier.padding(vertical = 8.dp)
+    CredentialListSectionHeader(
+        text = stringResource(R.string.get_dialog_heading_locked_password_managers)
     )
-    ContainerCard(
-        modifier = Modifier.fillMaxWidth().wrapContentHeight(),
-        shape = MaterialTheme.shapes.medium,
-    ) {
+    CredentialContainerCard {
         Column(
             modifier = Modifier.fillMaxWidth().wrapContentHeight(),
             verticalArrangement = Arrangement.spacedBy(2.dp),
@@ -471,17 +372,12 @@
     perUserNameCredentialEntryList: PerUserNameCredentialEntryList,
     onEntrySelected: (BaseEntry) -> Unit,
 ) {
-    TextSecondary(
+    CredentialListSectionHeader(
         text = stringResource(
             R.string.get_dialog_heading_for_username, perUserNameCredentialEntryList.userName
-        ),
-        style = MaterialTheme.typography.titleLarge,
-        modifier = Modifier.padding(vertical = 8.dp)
+        )
     )
-    ContainerCard(
-        modifier = Modifier.fillMaxWidth().wrapContentHeight(),
-        shape = MaterialTheme.shapes.medium,
-    ) {
+    CredentialContainerCard {
         Column(
             modifier = Modifier.fillMaxWidth().wrapContentHeight(),
             verticalArrangement = Arrangement.spacedBy(2.dp),
@@ -500,53 +396,28 @@
 ) {
     Entry(
         onClick = { onEntrySelected(credentialEntryInfo) },
-        icon = {
-            if (credentialEntryInfo.icon != null) {
-                Image(
-                    modifier = Modifier.padding(start = 10.dp).size(32.dp),
-                    bitmap = credentialEntryInfo.icon.toBitmap().asImageBitmap(),
-                    contentDescription = null,
-                )
-            } else {
-                Icon(
-                    modifier = Modifier.padding(start = 10.dp).size(32.dp),
-                    painter = painterResource(R.drawable.ic_other_sign_in),
-                    contentDescription = null,
-                    tint = LocalAndroidColorScheme.current.colorAccentPrimaryVariant
-                )
-            }
+        iconImageBitmap = credentialEntryInfo.icon?.toBitmap()?.asImageBitmap(),
+        // Fall back to iconPainter if iconImageBitmap isn't available
+        iconPainter =
+        if (credentialEntryInfo.icon == null) painterResource(R.drawable.ic_other_sign_in)
+        else null,
+        entryHeadlineText = credentialEntryInfo.userName,
+        entrySecondLineText = if (
+            credentialEntryInfo.credentialType == CredentialType.PASSWORD) {
+            "••••••••••••"
+        } else {
+            if (TextUtils.isEmpty(credentialEntryInfo.displayName))
+                credentialEntryInfo.credentialTypeDisplayName
+            else
+                credentialEntryInfo.credentialTypeDisplayName +
+                    stringResource(
+                        R.string.get_dialog_sign_in_type_username_separator
+                    ) +
+                    credentialEntryInfo.displayName
         },
-        label = {
-            Column() {
-                // TODO: fix the text values.
-                TextOnSurfaceVariant(
-                    text = credentialEntryInfo.userName,
-                    style = MaterialTheme.typography.titleLarge,
-                    modifier = Modifier.padding(top = 16.dp, start = 5.dp)
-                )
-                TextSecondary(
-                    text = if (
-                        credentialEntryInfo.credentialType == CredentialType.PASSWORD) {
-                        "••••••••••••"
-                    } else {
-                        if (TextUtils.isEmpty(credentialEntryInfo.displayName))
-                            credentialEntryInfo.credentialTypeDisplayName
-                        else
-                            credentialEntryInfo.credentialTypeDisplayName +
-                                stringResource(
-                                    R.string.get_dialog_sign_in_type_username_separator
-                                ) +
-                                credentialEntryInfo.displayName
-                    },
-                    style = MaterialTheme.typography.bodyMedium,
-                    modifier = Modifier.padding(bottom = 16.dp, start = 5.dp)
-                )
-            }
-        }
     )
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun AuthenticationEntryRow(
     authenticationEntryInfo: AuthenticationEntryInfo,
@@ -554,144 +425,66 @@
 ) {
     Entry(
         onClick = { onEntrySelected(authenticationEntryInfo) },
-        icon = {
-            Image(
-                modifier = Modifier.padding(start = 10.dp).size(32.dp),
-                bitmap = authenticationEntryInfo.icon.toBitmap().asImageBitmap(),
-                contentDescription = null
-            )
-        },
-        label = {
-            Row(
-                horizontalArrangement = Arrangement.SpaceBetween,
-                modifier = Modifier.fillMaxWidth().padding(horizontal = 5.dp),
-            ) {
-                Column() {
-                    TextOnSurfaceVariant(
-                        text = authenticationEntryInfo.title,
-                        style = MaterialTheme.typography.titleLarge,
-                        modifier = Modifier.padding(top = 16.dp)
-                    )
-                    TextSecondary(
-                        text = stringResource(
-                            if (authenticationEntryInfo.isUnlockedAndEmpty)
-                                R.string.locked_credential_entry_label_subtext_no_sign_in
-                            else R.string.locked_credential_entry_label_subtext_tap_to_unlock
-                    ),
-                        style = MaterialTheme.typography.bodyMedium,
-                        modifier = Modifier.padding(bottom = 16.dp)
-                    )
-                }
-                if (!authenticationEntryInfo.isUnlockedAndEmpty) {
-                    Icon(
-                        Icons.Outlined.Lock,
-                        null,
-                        Modifier.align(alignment = Alignment.CenterVertically).padding(end = 10.dp),
-                    )
-                }
-            }
-        }
+        iconImageBitmap = authenticationEntryInfo.icon.toBitmap().asImageBitmap(),
+        entryHeadlineText = authenticationEntryInfo.title,
+        entrySecondLineText = stringResource(
+            if (authenticationEntryInfo.isUnlockedAndEmpty)
+                R.string.locked_credential_entry_label_subtext_no_sign_in
+            else R.string.locked_credential_entry_label_subtext_tap_to_unlock
+        ),
+        isLockedAuthEntry = !authenticationEntryInfo.isUnlockedAndEmpty,
     )
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun ActionEntryRow(
     actionEntryInfo: ActionEntryInfo,
     onEntrySelected: (BaseEntry) -> Unit,
 ) {
-    TransparentBackgroundEntry(
-        icon = {
-            Image(
-                modifier = Modifier.padding(start = 10.dp).size(24.dp),
-                bitmap = actionEntryInfo.icon.toBitmap().asImageBitmap(),
-                contentDescription = null,
-            )
-        },
-        label = {
-            Column() {
-                TextOnSurfaceVariant(
-                    text = actionEntryInfo.title,
-                    style = MaterialTheme.typography.titleLarge,
-                    modifier = Modifier.padding(start = 8.dp),
-                )
-                if (actionEntryInfo.subTitle != null) {
-                    TextSecondary(
-                        text = actionEntryInfo.subTitle,
-                        style = MaterialTheme.typography.bodyMedium,
-                        modifier = Modifier.padding(start = 8.dp),
-                    )
-                }
-            }
-        },
+    ActionEntry(
+        iconImageBitmap = actionEntryInfo.icon.toBitmap().asImageBitmap(),
+        entryHeadlineText = actionEntryInfo.title,
+        entrySecondLineText = actionEntryInfo.subTitle,
         onClick = { onEntrySelected(actionEntryInfo) },
     )
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun RemoteCredentialSnackBarScreen(
     onClick: (Boolean) -> Unit,
     onCancel: () -> Unit,
 ) {
-    // TODO: Change the height, width and position according to the design
     Snackbar(
-        modifier = Modifier.padding(horizontal = 40.dp).padding(top = 700.dp),
-        shape = EntryShape.FullMediumRoundedCorner,
-        containerColor = LocalAndroidColorScheme.current.colorBackground,
-        contentColor = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
         action = {
             TextButton(
+                modifier = Modifier.padding(top = 4.dp, bottom = 4.dp, start = 16.dp)
+                    .heightIn(min = 32.dp),
                 onClick = { onClick(true) },
+                contentPadding =
+                PaddingValues(start = 0.dp, top = 6.dp, end = 0.dp, bottom = 6.dp),
             ) {
-                Text(text = stringResource(R.string.snackbar_action))
+                SnackbarActionText(text = stringResource(R.string.snackbar_action))
             }
         },
-        dismissAction = {
-            IconButton(onClick = onCancel) {
-                Icon(
-                    Icons.Filled.Close,
-                    contentDescription = stringResource(
-                        R.string.accessibility_close_button
-                    ),
-                    tint = LocalAndroidColorScheme.current.colorAccentTertiary
-                )
-            }
-        },
-    ) {
-        Text(text = stringResource(R.string.get_dialog_use_saved_passkey_for))
-    }
+        onDismiss = onCancel,
+        contentText = stringResource(R.string.get_dialog_use_saved_passkey_for),
+    )
 }
 
-@OptIn(ExperimentalMaterial3Api::class)
 @Composable
 fun EmptyAuthEntrySnackBarScreen(
     authenticationEntryList: List<AuthenticationEntryInfo>,
     onCancel: () -> Unit,
     onLastLockedAuthEntryNotFound: () -> Unit,
 ) {
-    val lastLocked = authenticationEntryList.firstOrNull({it.isLastUnlocked})
+    val lastLocked = authenticationEntryList.firstOrNull({ it.isLastUnlocked })
     if (lastLocked == null) {
         onLastLockedAuthEntryNotFound()
         return
     }
 
-    // TODO: Change the height, width and position according to the design
     Snackbar(
-        modifier = Modifier.padding(horizontal = 40.dp).padding(top = 700.dp),
-        shape = EntryShape.FullMediumRoundedCorner,
-        containerColor = LocalAndroidColorScheme.current.colorBackground,
-        contentColor = LocalAndroidColorScheme.current.colorAccentPrimaryVariant,
-        dismissAction = {
-            IconButton(onClick = onCancel) {
-                Icon(
-                    Icons.Filled.Close,
-                    contentDescription = stringResource(R.string.accessibility_close_button),
-                    tint = LocalAndroidColorScheme.current.colorAccentTertiary
-                )
-            }
-        },
-    ) {
-        Text(text = stringResource(R.string.no_sign_in_info_in, lastLocked.title))
-    }
+        onDismiss = onCancel,
+        contentText = stringResource(R.string.no_sign_in_info_in, lastLocked.providerDisplayName),
+    )
 }
\ 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 49415c0..9727d3f 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetModel.kt
@@ -37,7 +37,8 @@
 internal fun hasContentToDisplay(state: GetCredentialUiState): Boolean {
     return state.providerDisplayInfo.sortedUserNameToCredentialEntryList.isNotEmpty() ||
         state.providerDisplayInfo.authenticationEntryList.isNotEmpty() ||
-        state.providerDisplayInfo.remoteEntry != null
+        (state.providerDisplayInfo.remoteEntry != null &&
+            !state.requestDisplayInfo.preferImmediatelyAvailableCredentials)
 }
 
 data class ProviderInfo(
@@ -96,6 +97,7 @@
     pendingIntent: PendingIntent?,
     fillInIntent: Intent?,
     val title: String,
+    val providerDisplayName: String,
     val icon: Drawable,
     // The entry had been unlocked and turned out to be empty. Used to determine whether to
     // show "Tap to unlock" or "No sign-in info" for this entry.
@@ -140,11 +142,12 @@
     entrySubkey,
     pendingIntent,
     fillInIntent,
-    shouldTerminateUiUponSuccessfulProviderResult = false,
+    shouldTerminateUiUponSuccessfulProviderResult = true,
 )
 
 data class RequestDisplayInfo(
     val appName: String,
+    val preferImmediatelyAvailableCredentials: Boolean,
 )
 
 /**
@@ -245,7 +248,6 @@
 private fun toGetScreenState(
     providerDisplayInfo: ProviderDisplayInfo
 ): GetScreenState {
-
     return if (providerDisplayInfo.sortedUserNameToCredentialEntryList.isEmpty() &&
         providerDisplayInfo.remoteEntry == null &&
         providerDisplayInfo.authenticationEntryList.all { it.isUnlockedAndEmpty })
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt
index 15ae329..120e493 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/AndroidColorScheme.kt
@@ -22,12 +22,14 @@
 import androidx.compose.ui.graphics.Color
 import com.android.internal.R
 
+/** File copied from PlatformComposeCore. */
+
 /** CompositionLocal used to pass [AndroidColorScheme] down the tree. */
 val LocalAndroidColorScheme =
     staticCompositionLocalOf<AndroidColorScheme> {
         throw IllegalStateException(
             "No AndroidColorScheme configured. Make sure to use LocalAndroidColorScheme in a " +
-                    "Composable surrounded by a CredentialSelectorTheme {}."
+                "Composable surrounded by a PlatformTheme {}."
         )
     }
 
@@ -38,7 +40,6 @@
  * most of the colors in this class will be removed in favor of their M3 counterpart.
  */
 class AndroidColorScheme internal constructor(context: Context) {
-
     val colorPrimary = getColor(context, R.attr.colorPrimary)
     val colorPrimaryDark = getColor(context, R.attr.colorPrimaryDark)
     val colorAccent = getColor(context, R.attr.colorAccent)
@@ -66,10 +67,12 @@
     val colorForeground = getColor(context, R.attr.colorForeground)
     val colorForegroundInverse = getColor(context, R.attr.colorForegroundInverse)
 
-    private fun getColor(context: Context, attr: Int): Color {
-        val ta = context.obtainStyledAttributes(intArrayOf(attr))
-        @ColorInt val color = ta.getColor(0, 0)
-        ta.recycle()
-        return Color(color)
+    companion object {
+        fun getColor(context: Context, attr: Int): Color {
+            val ta = context.obtainStyledAttributes(intArrayOf(attr))
+            @ColorInt val color = ta.getColor(0, 0)
+            ta.recycle()
+            return Color(color)
+        }
     }
 }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Color.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Color.kt
index abb4bfb..c923845 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Color.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Color.kt
@@ -1,14 +1,30 @@
+/*
+ * 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.ui.theme
 
+import android.annotation.AttrRes
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.ReadOnlyComposable
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
 
-val Grey100 = Color(0xFFF1F3F4)
-val Purple200 = Color(0xFFBB86FC)
-val Purple500 = Color(0xFF6200EE)
-val Purple700 = Color(0xFF3700B3)
-val Teal200 = Color(0xFF03DAC5)
-val lightColorAccentSecondary = Color(0xFFC2E7FF)
-val lightBackgroundColor = Color(0xFFF0F0F0)
-val lightSurface1 = Color(0xFF6991D6)
-val textColorSecondary = Color(0xFF40484B)
-val textColorPrimary = Color(0xFF191C1D)
+/** Read the [Color] from the given [attribute]. */
+@Composable
+@ReadOnlyComposable
+fun colorAttr(@AttrRes attribute: Int): Color {
+    return AndroidColorScheme.getColor(LocalContext.current, attribute)
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/PlatformTheme.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/PlatformTheme.kt
new file mode 100644
index 0000000..662199a
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/PlatformTheme.kt
@@ -0,0 +1,64 @@
+/*
+ * 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.ui.theme
+
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalContext
+import com.android.credentialmanager.ui.theme.typography.TypeScaleTokens
+import com.android.credentialmanager.ui.theme.typography.TypefaceNames
+import com.android.credentialmanager.ui.theme.typography.TypefaceTokens
+import com.android.credentialmanager.ui.theme.typography.TypographyTokens
+import com.android.credentialmanager.ui.theme.typography.platformTypography
+
+/** File copied from PlatformComposeCore. */
+
+/** The Material 3 theme that should wrap all Platform Composables. */
+@Composable
+fun PlatformTheme(
+    isDarkTheme: Boolean = isSystemInDarkTheme(),
+    content: @Composable () -> Unit,
+) {
+    val context = LocalContext.current
+
+    // TODO(b/230605885): Define our color scheme.
+    val colorScheme =
+        if (isDarkTheme) {
+            dynamicDarkColorScheme(context)
+        } else {
+            dynamicLightColorScheme(context)
+        }
+    val androidColorScheme = AndroidColorScheme(context)
+    val typefaceNames = remember(context) { TypefaceNames.get(context) }
+    val typography =
+        remember(typefaceNames) {
+            platformTypography(TypographyTokens(TypeScaleTokens(TypefaceTokens(typefaceNames))))
+        }
+
+    MaterialTheme(colorScheme, typography = typography) {
+        CompositionLocalProvider(
+            LocalAndroidColorScheme provides androidColorScheme,
+        ) {
+            content()
+        }
+    }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Theme.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Theme.kt
deleted file mode 100644
index 3ca0e44..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Theme.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.android.credentialmanager.ui.theme
-
-import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.dynamicDarkColorScheme
-import androidx.compose.material3.dynamicLightColorScheme
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
-import androidx.compose.ui.platform.LocalContext
-
-@Composable
-fun CredentialSelectorTheme(
-  darkTheme: Boolean = isSystemInDarkTheme(),
-  content: @Composable () -> Unit
-) {
-  val context = LocalContext.current
-
-  val colorScheme =
-    if (darkTheme) {
-      dynamicDarkColorScheme(context)
-    } else {
-      dynamicLightColorScheme(context)
-    }
-  val androidColorScheme = AndroidColorScheme(context)
-  val typography = Typography
-
-  MaterialTheme(
-    colorScheme,
-    typography = typography,
-    shapes = Shapes
-  ) {
-    CompositionLocalProvider(
-      LocalAndroidColorScheme provides androidColorScheme,
-    ) {
-      content()
-    }
-  }
-}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Type.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Type.kt
deleted file mode 100644
index e09abbb..0000000
--- a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/Type.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.android.credentialmanager.ui.theme
-
-import androidx.compose.material3.Typography
-import androidx.compose.ui.text.TextStyle
-import androidx.compose.ui.text.font.FontFamily
-import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.sp
-
-// Set of Material typography styles to start with
-val Typography = Typography(
-  titleMedium = TextStyle(
-    fontFamily = FontFamily.Default,
-    fontWeight = FontWeight.Normal,
-    fontSize = 24.sp,
-    lineHeight = 32.sp,
-  ),
-  bodyLarge = TextStyle(
-    fontFamily = FontFamily.Default,
-    fontWeight = FontWeight.Normal,
-    fontSize = 14.sp,
-    lineHeight = 20.sp,
-  ),
-  bodyMedium = TextStyle(
-    fontFamily = FontFamily.Default,
-    fontWeight = FontWeight.Normal,
-    fontSize = 14.sp,
-    lineHeight = 20.sp,
-    color = textColorSecondary
-  ),
-  labelLarge = TextStyle(
-    fontFamily = FontFamily.Default,
-    fontWeight = FontWeight.Medium,
-    fontSize = 14.sp,
-    lineHeight = 20.sp,
-  ),
-  titleLarge = TextStyle(
-    fontFamily = FontFamily.Default,
-    fontWeight = FontWeight.Medium,
-    fontSize = 16.sp,
-    lineHeight = 24.sp,
-    color = textColorPrimary
-  ),
-
-  /* Other default text styles to override
-    button = TextStyle(
-        fontFamily = FontFamily.Default,
-        fontWeight = FontWeight.W500,
-        fontSize = 14.sp
-    ),
-    caption = TextStyle(
-        fontFamily = FontFamily.Default,
-        fontWeight = FontWeight.Normal,
-        fontSize = 12.sp
-    )
-    */
-)
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/PlatformTypography.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/PlatformTypography.kt
new file mode 100644
index 0000000..984e4f1
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/PlatformTypography.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.ui.theme.typography
+
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Typography
+
+/** File copied from PlatformComposeCore. */
+
+/**
+ * The typography for Platform Compose code.
+ *
+ * Do not use directly and call [MaterialTheme.typography] instead to access the different text
+ * styles.
+ */
+internal fun platformTypography(typographyTokens: TypographyTokens): Typography {
+    return Typography(
+        displayLarge = typographyTokens.displayLarge,
+        displayMedium = typographyTokens.displayMedium,
+        displaySmall = typographyTokens.displaySmall,
+        headlineLarge = typographyTokens.headlineLarge,
+        headlineMedium = typographyTokens.headlineMedium,
+        headlineSmall = typographyTokens.headlineSmall,
+        titleLarge = typographyTokens.titleLarge,
+        titleMedium = typographyTokens.titleMedium,
+        titleSmall = typographyTokens.titleSmall,
+        bodyLarge = typographyTokens.bodyLarge,
+        bodyMedium = typographyTokens.bodyMedium,
+        bodySmall = typographyTokens.bodySmall,
+        labelLarge = typographyTokens.labelLarge,
+        labelMedium = typographyTokens.labelMedium,
+        labelSmall = typographyTokens.labelSmall,
+    )
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypeScaleTokens.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypeScaleTokens.kt
new file mode 100644
index 0000000..b2dd207
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypeScaleTokens.kt
@@ -0,0 +1,98 @@
+/*
+ * 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.ui.theme.typography
+
+import androidx.compose.ui.unit.sp
+
+/** File copied from PlatformComposeCore. */
+internal class TypeScaleTokens(typefaceTokens: TypefaceTokens) {
+    val bodyLargeFont = typefaceTokens.plain
+    val bodyLargeLineHeight = 24.0.sp
+    val bodyLargeSize = 16.sp
+    val bodyLargeTracking = 0.0.sp
+    val bodyLargeWeight = TypefaceTokens.WeightRegular
+    val bodyMediumFont = typefaceTokens.plain
+    val bodyMediumLineHeight = 20.0.sp
+    val bodyMediumSize = 14.sp
+    val bodyMediumTracking = 0.0.sp
+    val bodyMediumWeight = TypefaceTokens.WeightRegular
+    val bodySmallFont = typefaceTokens.plain
+    val bodySmallLineHeight = 16.0.sp
+    val bodySmallSize = 12.sp
+    val bodySmallTracking = 0.1.sp
+    val bodySmallWeight = TypefaceTokens.WeightRegular
+    val displayLargeFont = typefaceTokens.brand
+    val displayLargeLineHeight = 64.0.sp
+    val displayLargeSize = 57.sp
+    val displayLargeTracking = 0.0.sp
+    val displayLargeWeight = TypefaceTokens.WeightRegular
+    val displayMediumFont = typefaceTokens.brand
+    val displayMediumLineHeight = 52.0.sp
+    val displayMediumSize = 45.sp
+    val displayMediumTracking = 0.0.sp
+    val displayMediumWeight = TypefaceTokens.WeightRegular
+    val displaySmallFont = typefaceTokens.brand
+    val displaySmallLineHeight = 44.0.sp
+    val displaySmallSize = 36.sp
+    val displaySmallTracking = 0.0.sp
+    val displaySmallWeight = TypefaceTokens.WeightRegular
+    val headlineLargeFont = typefaceTokens.brand
+    val headlineLargeLineHeight = 40.0.sp
+    val headlineLargeSize = 32.sp
+    val headlineLargeTracking = 0.0.sp
+    val headlineLargeWeight = TypefaceTokens.WeightRegular
+    val headlineMediumFont = typefaceTokens.brand
+    val headlineMediumLineHeight = 36.0.sp
+    val headlineMediumSize = 28.sp
+    val headlineMediumTracking = 0.0.sp
+    val headlineMediumWeight = TypefaceTokens.WeightRegular
+    val headlineSmallFont = typefaceTokens.brand
+    val headlineSmallLineHeight = 32.0.sp
+    val headlineSmallSize = 24.sp
+    val headlineSmallTracking = 0.0.sp
+    val headlineSmallWeight = TypefaceTokens.WeightRegular
+    val labelLargeFont = typefaceTokens.plain
+    val labelLargeLineHeight = 20.0.sp
+    val labelLargeSize = 14.sp
+    val labelLargeTracking = 0.0.sp
+    val labelLargeWeight = TypefaceTokens.WeightMedium
+    val labelMediumFont = typefaceTokens.plain
+    val labelMediumLineHeight = 16.0.sp
+    val labelMediumSize = 12.sp
+    val labelMediumTracking = 0.1.sp
+    val labelMediumWeight = TypefaceTokens.WeightMedium
+    val labelSmallFont = typefaceTokens.plain
+    val labelSmallLineHeight = 16.0.sp
+    val labelSmallSize = 11.sp
+    val labelSmallTracking = 0.1.sp
+    val labelSmallWeight = TypefaceTokens.WeightMedium
+    val titleLargeFont = typefaceTokens.brand
+    val titleLargeLineHeight = 28.0.sp
+    val titleLargeSize = 22.sp
+    val titleLargeTracking = 0.0.sp
+    val titleLargeWeight = TypefaceTokens.WeightRegular
+    val titleMediumFont = typefaceTokens.plain
+    val titleMediumLineHeight = 24.0.sp
+    val titleMediumSize = 16.sp
+    val titleMediumTracking = 0.0.sp
+    val titleMediumWeight = TypefaceTokens.WeightMedium
+    val titleSmallFont = typefaceTokens.plain
+    val titleSmallLineHeight = 20.0.sp
+    val titleSmallSize = 14.sp
+    val titleSmallTracking = 0.0.sp
+    val titleSmallWeight = TypefaceTokens.WeightMedium
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypefaceTokens.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypefaceTokens.kt
new file mode 100644
index 0000000..3cc761f
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypefaceTokens.kt
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+@file:OptIn(ExperimentalTextApi::class)
+
+package com.android.credentialmanager.ui.theme.typography
+
+import android.content.Context
+import androidx.compose.ui.text.ExperimentalTextApi
+import androidx.compose.ui.text.font.DeviceFontFamilyName
+import androidx.compose.ui.text.font.Font
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+
+/** File copied from PlatformComposeCore. */
+internal class TypefaceTokens(typefaceNames: TypefaceNames) {
+    companion object {
+        val WeightMedium = FontWeight.Medium
+        val WeightRegular = FontWeight.Normal
+    }
+
+    private val brandFont = DeviceFontFamilyName(typefaceNames.brand)
+    private val plainFont = DeviceFontFamilyName(typefaceNames.plain)
+
+    val brand =
+        FontFamily(
+            Font(brandFont, weight = WeightMedium),
+            Font(brandFont, weight = WeightRegular),
+        )
+    val plain =
+        FontFamily(
+            Font(plainFont, weight = WeightMedium),
+            Font(plainFont, weight = WeightRegular),
+        )
+}
+
+internal data class TypefaceNames
+private constructor(
+    val brand: String,
+    val plain: String,
+) {
+    private enum class Config(val configName: String, val default: String) {
+        Brand("config_headlineFontFamily", "sans-serif"),
+        Plain("config_bodyFontFamily", "sans-serif"),
+    }
+
+    companion object {
+        fun get(context: Context): TypefaceNames {
+            return TypefaceNames(
+                brand = getTypefaceName(context, Config.Brand),
+                plain = getTypefaceName(context, Config.Plain),
+            )
+        }
+
+        private fun getTypefaceName(context: Context, config: Config): String {
+            return context
+                .getString(context.resources.getIdentifier(config.configName, "string", "android"))
+                .takeIf { it.isNotEmpty() }
+                ?: config.default
+        }
+    }
+}
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypographyTokens.kt b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypographyTokens.kt
new file mode 100644
index 0000000..aadab92
--- /dev/null
+++ b/packages/CredentialManager/src/com/android/credentialmanager/ui/theme/typography/TypographyTokens.kt
@@ -0,0 +1,143 @@
+/*
+ * 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.ui.theme.typography
+
+import androidx.compose.ui.text.TextStyle
+
+/** File copied from PlatformComposeCore. */
+internal class TypographyTokens(typeScaleTokens: TypeScaleTokens) {
+    val bodyLarge =
+        TextStyle(
+            fontFamily = typeScaleTokens.bodyLargeFont,
+            fontWeight = typeScaleTokens.bodyLargeWeight,
+            fontSize = typeScaleTokens.bodyLargeSize,
+            lineHeight = typeScaleTokens.bodyLargeLineHeight,
+            letterSpacing = typeScaleTokens.bodyLargeTracking,
+        )
+    val bodyMedium =
+        TextStyle(
+            fontFamily = typeScaleTokens.bodyMediumFont,
+            fontWeight = typeScaleTokens.bodyMediumWeight,
+            fontSize = typeScaleTokens.bodyMediumSize,
+            lineHeight = typeScaleTokens.bodyMediumLineHeight,
+            letterSpacing = typeScaleTokens.bodyMediumTracking,
+        )
+    val bodySmall =
+        TextStyle(
+            fontFamily = typeScaleTokens.bodySmallFont,
+            fontWeight = typeScaleTokens.bodySmallWeight,
+            fontSize = typeScaleTokens.bodySmallSize,
+            lineHeight = typeScaleTokens.bodySmallLineHeight,
+            letterSpacing = typeScaleTokens.bodySmallTracking,
+        )
+    val displayLarge =
+        TextStyle(
+            fontFamily = typeScaleTokens.displayLargeFont,
+            fontWeight = typeScaleTokens.displayLargeWeight,
+            fontSize = typeScaleTokens.displayLargeSize,
+            lineHeight = typeScaleTokens.displayLargeLineHeight,
+            letterSpacing = typeScaleTokens.displayLargeTracking,
+        )
+    val displayMedium =
+        TextStyle(
+            fontFamily = typeScaleTokens.displayMediumFont,
+            fontWeight = typeScaleTokens.displayMediumWeight,
+            fontSize = typeScaleTokens.displayMediumSize,
+            lineHeight = typeScaleTokens.displayMediumLineHeight,
+            letterSpacing = typeScaleTokens.displayMediumTracking,
+        )
+    val displaySmall =
+        TextStyle(
+            fontFamily = typeScaleTokens.displaySmallFont,
+            fontWeight = typeScaleTokens.displaySmallWeight,
+            fontSize = typeScaleTokens.displaySmallSize,
+            lineHeight = typeScaleTokens.displaySmallLineHeight,
+            letterSpacing = typeScaleTokens.displaySmallTracking,
+        )
+    val headlineLarge =
+        TextStyle(
+            fontFamily = typeScaleTokens.headlineLargeFont,
+            fontWeight = typeScaleTokens.headlineLargeWeight,
+            fontSize = typeScaleTokens.headlineLargeSize,
+            lineHeight = typeScaleTokens.headlineLargeLineHeight,
+            letterSpacing = typeScaleTokens.headlineLargeTracking,
+        )
+    val headlineMedium =
+        TextStyle(
+            fontFamily = typeScaleTokens.headlineMediumFont,
+            fontWeight = typeScaleTokens.headlineMediumWeight,
+            fontSize = typeScaleTokens.headlineMediumSize,
+            lineHeight = typeScaleTokens.headlineMediumLineHeight,
+            letterSpacing = typeScaleTokens.headlineMediumTracking,
+        )
+    val headlineSmall =
+        TextStyle(
+            fontFamily = typeScaleTokens.headlineSmallFont,
+            fontWeight = typeScaleTokens.headlineSmallWeight,
+            fontSize = typeScaleTokens.headlineSmallSize,
+            lineHeight = typeScaleTokens.headlineSmallLineHeight,
+            letterSpacing = typeScaleTokens.headlineSmallTracking,
+        )
+    val labelLarge =
+        TextStyle(
+            fontFamily = typeScaleTokens.labelLargeFont,
+            fontWeight = typeScaleTokens.labelLargeWeight,
+            fontSize = typeScaleTokens.labelLargeSize,
+            lineHeight = typeScaleTokens.labelLargeLineHeight,
+            letterSpacing = typeScaleTokens.labelLargeTracking,
+        )
+    val labelMedium =
+        TextStyle(
+            fontFamily = typeScaleTokens.labelMediumFont,
+            fontWeight = typeScaleTokens.labelMediumWeight,
+            fontSize = typeScaleTokens.labelMediumSize,
+            lineHeight = typeScaleTokens.labelMediumLineHeight,
+            letterSpacing = typeScaleTokens.labelMediumTracking,
+        )
+    val labelSmall =
+        TextStyle(
+            fontFamily = typeScaleTokens.labelSmallFont,
+            fontWeight = typeScaleTokens.labelSmallWeight,
+            fontSize = typeScaleTokens.labelSmallSize,
+            lineHeight = typeScaleTokens.labelSmallLineHeight,
+            letterSpacing = typeScaleTokens.labelSmallTracking,
+        )
+    val titleLarge =
+        TextStyle(
+            fontFamily = typeScaleTokens.titleLargeFont,
+            fontWeight = typeScaleTokens.titleLargeWeight,
+            fontSize = typeScaleTokens.titleLargeSize,
+            lineHeight = typeScaleTokens.titleLargeLineHeight,
+            letterSpacing = typeScaleTokens.titleLargeTracking,
+        )
+    val titleMedium =
+        TextStyle(
+            fontFamily = typeScaleTokens.titleMediumFont,
+            fontWeight = typeScaleTokens.titleMediumWeight,
+            fontSize = typeScaleTokens.titleMediumSize,
+            lineHeight = typeScaleTokens.titleMediumLineHeight,
+            letterSpacing = typeScaleTokens.titleMediumTracking,
+        )
+    val titleSmall =
+        TextStyle(
+            fontFamily = typeScaleTokens.titleSmallFont,
+            fontWeight = typeScaleTokens.titleSmallWeight,
+            fontSize = typeScaleTokens.titleSmallSize,
+            lineHeight = typeScaleTokens.titleSmallLineHeight,
+            letterSpacing = typeScaleTokens.titleSmallTracking,
+        )
+}
diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml
index b194738..c2aaeac 100644
--- a/packages/DynamicSystemInstallationService/AndroidManifest.xml
+++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml
@@ -21,12 +21,7 @@
             android:exported="true"
             android:permission="android.permission.INSTALL_DYNAMIC_SYSTEM"
             android:foregroundServiceType="systemExempted"
-            android:process=":dynsystem">
-            <intent-filter>
-                <action android:name="android.os.image.action.NOTIFY_IF_IN_USE" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </service>
+            android:process=":dynsystem" />
 
         <activity android:name=".VerificationActivity"
             android:exported="true"
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index af20a4b..750c156 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -70,7 +70,7 @@
         "src/**/*.kt",
     ],
 
-    min_sdk_version: "29",
+    min_sdk_version: "30",
 
 }
 
diff --git a/packages/SettingsLib/DeviceStateRotationLock/OWNERS b/packages/SettingsLib/DeviceStateRotationLock/OWNERS
new file mode 100644
index 0000000..091df26
--- /dev/null
+++ b/packages/SettingsLib/DeviceStateRotationLock/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/packages/SettingsLib/src/com/android/settingslib/devicestate/OWNERS
\ No newline at end of file
diff --git a/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml b/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
index 940f5c9..78a7408 100644
--- a/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
+++ b/packages/SettingsLib/Spa/.idea/codeStyles/Project.xml
@@ -1,17 +1,12 @@
 <component name="ProjectCodeStyleConfiguration">
   <code_scheme name="Project" version="173">
     <JetCodeStyleSettings>
-      <option name="PACKAGES_TO_USE_STAR_IMPORTS">
-        <value />
-      </option>
       <option name="PACKAGES_IMPORT_LAYOUT">
         <value>
           <package name="" alias="false" withSubpackages="true" />
           <package name="" alias="true" withSubpackages="true" />
         </value>
       </option>
-      <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
-      <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
       <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
     </JetCodeStyleSettings>
     <XML>
diff --git a/packages/SettingsLib/Spa/build.gradle b/packages/SettingsLib/Spa/build.gradle
index 42af999..643af75 100644
--- a/packages/SettingsLib/Spa/build.gradle
+++ b/packages/SettingsLib/Spa/build.gradle
@@ -24,7 +24,7 @@
     }
 }
 plugins {
-    id 'com.android.application' version '7.3.1' apply false
-    id 'com.android.library' version '7.3.1' apply false
+    id 'com.android.application' version '8.0.0-beta01' apply false
+    id 'com.android.library' version '8.0.0-beta01' apply false
     id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
 }
diff --git a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
index bd7e7ff..53b24b0 100644
--- a/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
+++ b/packages/SettingsLib/Spa/gradle/wrapper/gradle-wrapper.properties
@@ -16,7 +16,7 @@
 
 #Thu Jul 14 10:36:06 CST 2022
 distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-rc-1-bin.zip
 distributionPath=wrapper/dists
 zipStorePath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
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 724588f..3fdb1d1 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
@@ -77,9 +77,8 @@
         return true
     }
 
-    fun isEnabled(): Boolean {
-        return getPageProvider(sppName)?.isEnabled(arguments) ?: false
-    }
+    fun isEnabled(): Boolean =
+        SpaEnvironment.IS_DEBUG || getPageProvider(sppName)?.isEnabled(arguments) ?: false
 
     fun getTitle(): String {
         return getPageProvider(sppName)?.getTitle(arguments) ?: ""
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 02962a5..2d956d5 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
@@ -88,4 +88,13 @@
     open val sliceProviderAuthorities: String? = null
 
     // TODO: add other environment setup here.
+    companion object {
+        /**
+         * Whether debug mode is on or off.
+         *
+         * If set to true, this will also enable all the pages under development (allows browsing
+         * and searching).
+         */
+        const val IS_DEBUG = false
+    }
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
index 5e6c614..0552c40 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/button/ActionButtons.kt
@@ -24,7 +24,6 @@
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.RowScope
-import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxHeight
 import androidx.compose.foundation.layout.height
 import androidx.compose.foundation.layout.padding
@@ -46,6 +45,7 @@
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.graphics.RectangleShape
 import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import com.android.settingslib.spa.framework.theme.SettingsDimension
@@ -100,11 +100,16 @@
                 contentDescription = null,
                 modifier = Modifier.size(SettingsDimension.itemIconSize),
             )
-            Spacer(Modifier.height(4.dp))
-            Text(
-                text = actionButton.text,
-                style = MaterialTheme.typography.labelMedium,
-            )
+            Box(
+                modifier = Modifier.padding(top = 4.dp).fillMaxHeight(),
+                contentAlignment = Alignment.Center,
+            ) {
+                Text(
+                    text = actionButton.text,
+                    textAlign = TextAlign.Center,
+                    style = MaterialTheme.typography.labelMedium,
+                )
+            }
         }
     }
 }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
index 18b20733..1a7d896 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppRepository.kt
@@ -19,7 +19,6 @@
 import android.content.Context
 import android.content.pm.ApplicationInfo
 import android.graphics.drawable.Drawable
-import android.os.UserManager
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.State
 import androidx.compose.runtime.produceState
@@ -28,6 +27,7 @@
 import com.android.settingslib.Utils
 import com.android.settingslib.spa.framework.compose.rememberContext
 import com.android.settingslib.spaprivileged.R
+import com.android.settingslib.spaprivileged.framework.common.userManager
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
 
@@ -42,23 +42,25 @@
         val context = LocalContext.current
         return produceState(initialValue = stringResource(R.string.summary_placeholder), app) {
             withContext(Dispatchers.IO) {
-                if (isClonedAppPage || isCloneApp(context, app)) {
-                    value = context.getString(R.string.cloned_app_info_label, loadLabel(app))
+                value = if (isClonedAppPage || isCloneApp(context, app)) {
+                    context.getString(R.string.cloned_app_info_label, loadLabel(app))
                 } else {
-                    value = loadLabel(app)
+                    loadLabel(app)
                 }
             }
         }
     }
 
     private fun isCloneApp(context: Context, app: ApplicationInfo): Boolean {
-        val userManager = context.getSystemService(UserManager::class.java)!!
-        val userInfo = userManager.getUserInfo(app.userId)
+        val userInfo = context.userManager.getUserInfo(app.userId)
         return userInfo != null && userInfo.isCloneProfile
     }
 
     @Composable
     fun produceIcon(app: ApplicationInfo): State<Drawable?>
+
+    @Composable
+    fun produceIconContentDescription(app: ApplicationInfo): State<String?>
 }
 
 internal class AppRepositoryImpl(private val context: Context) : AppRepository {
@@ -69,8 +71,22 @@
     @Composable
     override fun produceIcon(app: ApplicationInfo) =
         produceState<Drawable?>(initialValue = null, app) {
-            withContext(Dispatchers.Default) {
+            withContext(Dispatchers.IO) {
                 value = Utils.getBadgedIcon(context, app)
             }
         }
+
+    @Composable
+    override fun produceIconContentDescription(app: ApplicationInfo) =
+        produceState<String?>(initialValue = null, app) {
+            withContext(Dispatchers.IO) {
+                value = when {
+                    context.userManager.isManagedProfile(app.userId) -> {
+                        context.getString(R.string.category_work)
+                    }
+
+                    else -> null
+                }
+            }
+        }
 }
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
index 602df54..e3ea2e7 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppInfo.kt
@@ -32,6 +32,7 @@
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
 import com.android.settingslib.spa.framework.compose.rememberDrawablePainter
@@ -50,7 +51,8 @@
                 .padding(
                     horizontal = SettingsDimension.itemPaddingStart,
                     vertical = SettingsDimension.itemPaddingVertical,
-                ),
+                )
+                .semantics(mergeDescendants = true) {},
             horizontalAlignment = Alignment.CenterHorizontally,
         ) {
             val app = packageInfo.applicationInfo
@@ -93,8 +95,8 @@
     val appRepository = rememberAppRepository()
     Image(
         painter = rememberDrawablePainter(appRepository.produceIcon(app).value),
-        contentDescription = null,
-        modifier = Modifier.size(size)
+        contentDescription = appRepository.produceIconContentDescription(app).value,
+        modifier = Modifier.size(size),
     )
 }
 
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
index fc40aed..4f0cdde 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppListViewModelTest.kt
@@ -103,6 +103,9 @@
 
         @Composable
         override fun produceIcon(app: ApplicationInfo) = stateOf(null)
+
+        @Composable
+        override fun produceIconContentDescription(app: ApplicationInfo) = stateOf(null)
     }
 
     private companion object {
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppRepositoryTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppRepositoryTest.kt
new file mode 100644
index 0000000..26caa01
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/model/app/AppRepositoryTest.kt
@@ -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.settingslib.spaprivileged.model.app
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.os.UserManager
+import androidx.compose.runtime.State
+import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.framework.compose.stateOf
+import com.android.settingslib.spa.testutils.delay
+import com.android.settingslib.spaprivileged.R
+import com.android.settingslib.spaprivileged.framework.common.userManager
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Spy
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoRule
+import org.mockito.Mockito.`when` as whenever
+
+@RunWith(AndroidJUnit4::class)
+class AppRepositoryTest {
+    @get:Rule
+    val composeTestRule = createComposeRule()
+
+    @get:Rule
+    val mockito: MockitoRule = MockitoJUnit.rule()
+
+    @Spy
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    @Mock
+    private lateinit var userManager: UserManager
+
+    private lateinit var appRepository: AppRepositoryImpl
+
+    @Before
+    fun setUp() {
+        whenever(context.userManager).thenReturn(userManager)
+        appRepository = AppRepositoryImpl(context)
+    }
+
+    @Test
+    fun produceIconContentDescription_workProfile() {
+        whenever(userManager.isManagedProfile(APP.userId)).thenReturn(true)
+
+        val contentDescription = produceIconContentDescription()
+
+        assertThat(contentDescription.value).isEqualTo(context.getString(R.string.category_work))
+    }
+
+    @Test
+    fun produceIconContentDescription_personalProfile() {
+        whenever(userManager.isManagedProfile(APP.userId)).thenReturn(false)
+
+        val contentDescription = produceIconContentDescription()
+
+        assertThat(contentDescription.value).isNull()
+    }
+
+    private fun produceIconContentDescription(): State<String?> {
+        var contentDescription: State<String?> = stateOf(null)
+        composeTestRule.setContent {
+            contentDescription = appRepository.produceIconContentDescription(APP)
+        }
+        composeTestRule.delay()
+        return contentDescription
+    }
+
+    private companion object {
+        const val UID = 123
+        val APP = ApplicationInfo().apply {
+            uid = UID
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/arrays.xml b/packages/SettingsLib/res/values-af/arrays.xml
index 1907b3e..28f7c50 100644
--- a/packages/SettingsLib/res/values-af/arrays.xml
+++ b/packages/SettingsLib/res/values-af/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Het gefiltreer geaktiveer"</item>
     <item msgid="2779123106632690576">"Geaktiveer"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Opskrifte is gefiltreer"</item>
-    <item msgid="4818549483446395865">"A2DP-mediapakkette is gefiltreer"</item>
-    <item msgid="8207123990453243311">"RFCOMM-kanaal is gefiltreer"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Gedeaktiveer"</item>
-    <item msgid="5884245882825346396">"Wonder"</item>
-    <item msgid="6569400572915342949">"Opskrif"</item>
-    <item msgid="1239386221416967664">"Volledige filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (verstek)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 31f50e8..3de581e 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Wekkers en onthounotas"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Laat toe dat wekkers en onthounotas gestel word"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Wekkers en onthounotas"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie program toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die program op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie program geskeduleer is, nie werk nie."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Laat hierdie app toe om wekkers te stel en tydsensitiewe handelinge te skeduleer. Dit laat die app op die agtergrond werk, wat meer batterykrag kan gebruik.\n\nAs hierdie toestemming af is, sal bestaande wekkers en tydgegronde geleenthede wat deur hierdie app geskeduleer is, nie werk nie."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"skedule, wekker, onthounota, horlosie"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Skakel aan"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Skakel Moenie steur nie aan"</string>
diff --git a/packages/SettingsLib/res/values-am/arrays.xml b/packages/SettingsLib/res/values-am/arrays.xml
index ad0f1ed..c423d3c 100644
--- a/packages/SettingsLib/res/values-am/arrays.xml
+++ b/packages/SettingsLib/res/values-am/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ማጣሪያን አንቃ"</item>
     <item msgid="2779123106632690576">"ነቅቷል"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ራስጌዎች ተጣርተዋል"</item>
-    <item msgid="4818549483446395865">"የA2DP ሚዲያ ፓኬቶች ተጣርተዋል"</item>
-    <item msgid="8207123990453243311">"የRFCOMM ሰርጥ ተጣርቷል"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ተሰናክሏል"</item>
-    <item msgid="5884245882825346396">"ማጂክ"</item>
-    <item msgid="6569400572915342949">"የራስጌ ጽሑፍ"</item>
-    <item msgid="1239386221416967664">"ሙሉ ማጣሪያ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ነባሪ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ar/arrays.xml b/packages/SettingsLib/res/values-ar/arrays.xml
index cede18e..cf46a8f 100644
--- a/packages/SettingsLib/res/values-ar/arrays.xml
+++ b/packages/SettingsLib/res/values-ar/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"تمّ تفعيل التصفية"</item>
     <item msgid="2779123106632690576">"مفعّل"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"العناوين المفلترة"</item>
-    <item msgid="4818549483446395865">"‏حُزم وسائط A2DP مفلترة"</item>
-    <item msgid="8207123990453243311">"‏قناة بروتوكول RFCOMM مفلترة"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"حُزم البيانات غير المفعّلة"</item>
-    <item msgid="5884245882825346396">"سِحري"</item>
-    <item msgid="6569400572915342949">"العنوان"</item>
-    <item msgid="1239386221416967664">"فلترة كاملة"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP 1.5 (تلقائي)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-as/arrays.xml b/packages/SettingsLib/res/values-as/arrays.xml
index c52d27e2..284ca12 100644
--- a/packages/SettingsLib/res/values-as/arrays.xml
+++ b/packages/SettingsLib/res/values-as/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"সক্ষম কৰাবিলাক ফিল্টাৰ কৰা হৈছে"</item>
     <item msgid="2779123106632690576">"সক্ষম কৰা আছে"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"হেডাৰ ফিল্টাৰ কৰা হৈছে"</item>
-    <item msgid="4818549483446395865">"A2DP মিডিয়াৰ পেকেট ফিল্টাৰ কৰা হৈছে"</item>
-    <item msgid="8207123990453243311">"RFCOMM চেনেল ফিল্টাৰ কৰা হৈছে"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"অক্ষম কৰা আছে"</item>
-    <item msgid="5884245882825346396">"যাদু"</item>
-    <item msgid="6569400572915342949">"হেডাৰ"</item>
-    <item msgid="1239386221416967664">"সম্পূৰ্ণ ফিল্টাৰ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ডিফ’ল্ট)"</item>
     <item msgid="1637054408779685086">"AVRCP ১.৩"</item>
diff --git a/packages/SettingsLib/res/values-az/arrays.xml b/packages/SettingsLib/res/values-az/arrays.xml
index 9605c51..ff0054b 100644
--- a/packages/SettingsLib/res/values-az/arrays.xml
+++ b/packages/SettingsLib/res/values-az/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrləmə aktivdir"</item>
     <item msgid="2779123106632690576">"Aktivdir"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Başlıqlar Filtrlənib"</item>
-    <item msgid="4818549483446395865">"A2DP Media Paketləri Filtrlənib"</item>
-    <item msgid="8207123990453243311">"RFCOMM Kanalı Filtrlənib"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Deaktiv"</item>
-    <item msgid="5884245882825346396">"Sehr"</item>
-    <item msgid="6569400572915342949">"Başlıq"</item>
-    <item msgid="1239386221416967664">"Tam Filtr"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Defolt)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
index 618748b..32071e5 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogućeno"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
-    <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
-    <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Onemogućeno"</item>
-    <item msgid="5884245882825346396">"Magija"</item>
-    <item msgid="6569400572915342949">"Zaglavlje"</item>
-    <item msgid="1239386221416967664">"Potpuni filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (podrazumevano)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-be/arrays.xml b/packages/SettingsLib/res/values-be/arrays.xml
index 117f0b4..a60d354 100644
--- a/packages/SettingsLib/res/values-be/arrays.xml
+++ b/packages/SettingsLib/res/values-be/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Уключана з фільтрацыяй"</item>
     <item msgid="2779123106632690576">"Уключана"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Адфільтраваны загалоўкі"</item>
-    <item msgid="4818549483446395865">"Адфільтраваны пакеты мультымедыя A2DP"</item>
-    <item msgid="8207123990453243311">"Адфільтраваны канал RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Адключана"</item>
-    <item msgid="5884245882825346396">"Спецыяльная фраза"</item>
-    <item msgid="6569400572915342949">"Загаловак"</item>
-    <item msgid="1239386221416967664">"Поўная фільтрацыя"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (стандартная)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bg/arrays.xml b/packages/SettingsLib/res/values-bg/arrays.xml
index cf643c8..d778ca2 100644
--- a/packages/SettingsLib/res/values-bg/arrays.xml
+++ b/packages/SettingsLib/res/values-bg/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Филтрирането е активирано"</item>
     <item msgid="2779123106632690576">"Активирано"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Заглавките са филтрирани"</item>
-    <item msgid="4818549483446395865">"Мултимедийните пакети A2DP са филтрирани"</item>
-    <item msgid="8207123990453243311">"Каналът RFCOMM е филтриран"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Деактивирано"</item>
-    <item msgid="5884245882825346396">"Магия"</item>
-    <item msgid="6569400572915342949">"Заглавка"</item>
-    <item msgid="1239386221416967664">"Пълен филтър"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (основно)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bn/arrays.xml b/packages/SettingsLib/res/values-bn/arrays.xml
index 1a7652d..dbb738c 100644
--- a/packages/SettingsLib/res/values-bn/arrays.xml
+++ b/packages/SettingsLib/res/values-bn/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ফিল্টার করা চালু আছে"</item>
     <item msgid="2779123106632690576">"চালু করা আছে"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"হেডার ফিল্টার করা হয়েছে"</item>
-    <item msgid="4818549483446395865">"A2DP মিডিয়া প্যাকেট ফিল্টার করা হয়েছে"</item>
-    <item msgid="8207123990453243311">"RFCOMM চ্যানেল ফিল্টার করা হয়েছে"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"বন্ধ করা আছে"</item>
-    <item msgid="5884245882825346396">"ম্যাজিক"</item>
-    <item msgid="6569400572915342949">"হেডার"</item>
-    <item msgid="1239386221416967664">"সম্পূর্ণ ফিল্টার"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ডিফল্ট)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 2ab1b79..740e704 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogućeno"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
-    <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
-    <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Onemogućeno"</item>
-    <item msgid="5884245882825346396">"Magija"</item>
-    <item msgid="6569400572915342949">"Zaglavlje"</item>
-    <item msgid="1239386221416967664">"Potpuni filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (zadano)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index e8cabfa..1aa8ff3 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmi i podsjetnici"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Dozvoli postavljanje alarma i podsjetnika"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmi i podsjetnici"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu koje je ova aplikacija zakazala neće funkcionirati."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Dozvolite ovoj aplikaciji da postavlja alarme i zakazuje vremenski osjetljive radnje. Ovim će se omogućiti aplikaciji da radi u pozadini, čime se može povećati potrošnja baterije.\n\nAko je ovo odobrenje isključeno, postojeći alarmi i događaji zasnovani na vremenu, a koje je ova aplikacija zakazala, neće funkcionirati."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"raspored, alarm, podsjetnik, sat"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Uključi"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Uključi način rada Ne ometaj"</string>
diff --git a/packages/SettingsLib/res/values-ca/arrays.xml b/packages/SettingsLib/res/values-ca/arrays.xml
index 00a126c..4e437ba 100644
--- a/packages/SettingsLib/res/values-ca/arrays.xml
+++ b/packages/SettingsLib/res/values-ca/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Activat amb filtres"</item>
     <item msgid="2779123106632690576">"Activat"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Capçaleres filtrades"</item>
-    <item msgid="4818549483446395865">"Paquets multimèdia A2DP filtrats"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrat"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desactivat"</item>
-    <item msgid="5884245882825346396">"Màgia"</item>
-    <item msgid="6569400572915342949">"Capçalera"</item>
-    <item msgid="1239386221416967664">"Filtre complet"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminada)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 83b32d4..f14befd 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes i recordatoris"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permet la configuració d\'alarmes i recordatoris"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes i recordatoris"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permet que aquesta aplicació configuri alarmes i programi accions a una hora determinada. Això permet a l\'aplicació executar-se en segon pla i, per tant, és possible que consumeixi més bateria.\n\nSi aquest permís està desactivat, les alarmes i els esdeveniments que ja hagi programat l\'aplicació no funcionaran."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programació, alarma, recordatori, rellotge"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activa"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activa el mode No molestis"</string>
diff --git a/packages/SettingsLib/res/values-cs/arrays.xml b/packages/SettingsLib/res/values-cs/arrays.xml
index a4bd21f..e1a5aef 100644
--- a/packages/SettingsLib/res/values-cs/arrays.xml
+++ b/packages/SettingsLib/res/values-cs/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Povolit filtrované"</item>
     <item msgid="2779123106632690576">"Zapnuto"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Záhlaví filtrována"</item>
-    <item msgid="4818549483446395865">"Mediální balíčky A2DP filtrovány"</item>
-    <item msgid="8207123990453243311">"Kanál RFCOMM filtrován"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Zakázáno"</item>
-    <item msgid="5884245882825346396">"Komplexní hodnocení"</item>
-    <item msgid="6569400572915342949">"Záhlaví"</item>
-    <item msgid="1239386221416967664">"Úplný filtr"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (výchozí)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-da/arrays.xml b/packages/SettingsLib/res/values-da/arrays.xml
index 37da365..03cab20 100644
--- a/packages/SettingsLib/res/values-da/arrays.xml
+++ b/packages/SettingsLib/res/values-da/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtreret er aktiveret"</item>
     <item msgid="2779123106632690576">"Aktiveret"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Overskrifter filtreret"</item>
-    <item msgid="4818549483446395865">"A2DP-mediepakker filtreret"</item>
-    <item msgid="8207123990453243311">"RFCOMM-kanal filtreret"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Deaktiveret"</item>
-    <item msgid="5884245882825346396">"Magi"</item>
-    <item msgid="6569400572915342949">"Overskrift"</item>
-    <item msgid="1239386221416967664">"Fuldt filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-de/arrays.xml b/packages/SettingsLib/res/values-de/arrays.xml
index 2241666..c5dcc10 100644
--- a/packages/SettingsLib/res/values-de/arrays.xml
+++ b/packages/SettingsLib/res/values-de/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filter aktiviert"</item>
     <item msgid="2779123106632690576">"Aktiviert"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Header gefiltert"</item>
-    <item msgid="4818549483446395865">"A2DP-Medienpakete gefiltert"</item>
-    <item msgid="8207123990453243311">"RFCOMM-Kanal gefiltert"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Deaktiviert"</item>
-    <item msgid="5884245882825346396">"Magie"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Vollständig gefiltert"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-el/arrays.xml b/packages/SettingsLib/res/values-el/arrays.xml
index 1a824c1..6486b3d 100644
--- a/packages/SettingsLib/res/values-el/arrays.xml
+++ b/packages/SettingsLib/res/values-el/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Ενεργοποιήθηκε το φιλτράρισμα"</item>
     <item msgid="2779123106632690576">"Ενεργοποιήθηκε"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Φιλτραρισμένες κεφαλίδες"</item>
-    <item msgid="4818549483446395865">"Φιλτραρισμένα πακέτα μέσων A2DP"</item>
-    <item msgid="8207123990453243311">"Φιλτραρισμένο κανάλι RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Ανενεργό"</item>
-    <item msgid="5884245882825346396">"Μαγεία"</item>
-    <item msgid="6569400572915342949">"Κεφαλίδα"</item>
-    <item msgid="1239386221416967664">"Πλήρες φίλτρο"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Προεπιλογή)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rAU/arrays.xml b/packages/SettingsLib/res/values-en-rAU/arrays.xml
index de63386..9a7390e 100644
--- a/packages/SettingsLib/res/values-en-rAU/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rAU/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Enabled Filtered"</item>
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Headers filtered"</item>
-    <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
-    <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Disabled"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Full filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rCA/arrays.xml b/packages/SettingsLib/res/values-en-rCA/arrays.xml
index 0af8b4e..184d210 100644
--- a/packages/SettingsLib/res/values-en-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rCA/arrays.xml
@@ -64,15 +64,15 @@
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Headers Filtered"</item>
-    <item msgid="4818549483446395865">"A2DP Media Packets Filtered"</item>
-    <item msgid="8207123990453243311">"RFCOMM Channel Filtered"</item>
+    <item msgid="195768089203590086">"Leave only ACL headers"</item>
+    <item msgid="2776218217644557831">"Filter A2DP media packets"</item>
+    <item msgid="8163235976612675092">"Filter RFCOMM channel"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Disabled"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Full Filter"</item>
+    <item msgid="3961868665260627524">"Disable"</item>
+    <item msgid="2505973306504851132">"Fill with string of characters"</item>
+    <item msgid="5883011000629613855">"Leave only header"</item>
+    <item msgid="1051534112762023603">"Fully remove"</item>
   </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
diff --git a/packages/SettingsLib/res/values-en-rGB/arrays.xml b/packages/SettingsLib/res/values-en-rGB/arrays.xml
index de63386..9a7390e 100644
--- a/packages/SettingsLib/res/values-en-rGB/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rGB/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Enabled Filtered"</item>
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Headers filtered"</item>
-    <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
-    <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Disabled"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Full filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rIN/arrays.xml b/packages/SettingsLib/res/values-en-rIN/arrays.xml
index de63386..9a7390e 100644
--- a/packages/SettingsLib/res/values-en-rIN/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rIN/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Enabled Filtered"</item>
     <item msgid="2779123106632690576">"Enabled"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Headers filtered"</item>
-    <item msgid="4818549483446395865">"A2DP media packets filtered"</item>
-    <item msgid="8207123990453243311">"RFCOMM channel filtered"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Disabled"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Full filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-en-rXC/arrays.xml b/packages/SettingsLib/res/values-en-rXC/arrays.xml
index 30c9a49..dec70f4 100644
--- a/packages/SettingsLib/res/values-en-rXC/arrays.xml
+++ b/packages/SettingsLib/res/values-en-rXC/arrays.xml
@@ -64,15 +64,15 @@
     <item msgid="2779123106632690576">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‎‎‎Enabled‎‏‎‎‏‎"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎Headers Filtered‎‏‎‎‏‎"</item>
-    <item msgid="4818549483446395865">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎A2DP Media Packets Filtered‎‏‎‎‏‎"</item>
-    <item msgid="8207123990453243311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎RFCOMM Channel Filtered‎‏‎‎‏‎"</item>
+    <item msgid="195768089203590086">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎Leave only ACL headers‎‏‎‎‏‎"</item>
+    <item msgid="2776218217644557831">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎Filter A2DP media packets‎‏‎‎‏‎"</item>
+    <item msgid="8163235976612675092">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‎‎Filter RFCOMM channel‎‏‎‎‏‎"</item>
   </string-array>
   <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‏‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‏‏‎Disabled‎‏‎‎‏‎"</item>
-    <item msgid="5884245882825346396">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‎‎Magic‎‏‎‎‏‎"</item>
-    <item msgid="6569400572915342949">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎Header‎‏‎‎‏‎"</item>
-    <item msgid="1239386221416967664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‎Full Filter‎‏‎‎‏‎"</item>
+    <item msgid="3961868665260627524">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎‏‎‎‎‏‎‎‎Disable‎‏‎‎‏‎"</item>
+    <item msgid="2505973306504851132">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‏‏‏‎‎‎Fill with string of characters‎‏‎‎‏‎"</item>
+    <item msgid="5883011000629613855">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎Leave only header‎‏‎‎‏‎"</item>
+    <item msgid="1051534112762023603">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‏‎Fully remove‎‏‎‎‏‎"</item>
   </string-array>
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎AVRCP 1.5 (Default)‎‏‎‎‏‎"</item>
diff --git a/packages/SettingsLib/res/values-es-rUS/arrays.xml b/packages/SettingsLib/res/values-es-rUS/arrays.xml
index e2a36c6..771690d 100644
--- a/packages/SettingsLib/res/values-es-rUS/arrays.xml
+++ b/packages/SettingsLib/res/values-es-rUS/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrado habilitado"</item>
     <item msgid="2779123106632690576">"Habilitado"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Títulos filtrados"</item>
-    <item msgid="4818549483446395865">"Paquetes de medios A2DP filtrados"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Inhabilitada"</item>
-    <item msgid="5884245882825346396">"Automático"</item>
-    <item msgid="6569400572915342949">"Título"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-es/arrays.xml b/packages/SettingsLib/res/values-es/arrays.xml
index b5e035c..e07f9dc 100644
--- a/packages/SettingsLib/res/values-es/arrays.xml
+++ b/packages/SettingsLib/res/values-es/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Habilitado con filtros"</item>
     <item msgid="2779123106632690576">"Habilitado"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Encabezados filtrados"</item>
-    <item msgid="4818549483446395865">"Paquetes de medios A2DP filtrados"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Inhabilitado"</item>
-    <item msgid="5884245882825346396">"Mágico"</item>
-    <item msgid="6569400572915342949">"Encabezado"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-et/arrays.xml b/packages/SettingsLib/res/values-et/arrays.xml
index d910a0e..34448a7 100644
--- a/packages/SettingsLib/res/values-et/arrays.xml
+++ b/packages/SettingsLib/res/values-et/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Luba filtreeritud"</item>
     <item msgid="2779123106632690576">"Lubatud"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtreeritud päised"</item>
-    <item msgid="4818549483446395865">"Filtreeritud A2DP meediapaketid"</item>
-    <item msgid="8207123990453243311">"Filtreeritud RFCOMM-kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Keelatud"</item>
-    <item msgid="5884245882825346396">"Maagiline"</item>
-    <item msgid="6569400572915342949">"Päis"</item>
-    <item msgid="1239386221416967664">"Täielik filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (vaikeseade)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-eu/arrays.xml b/packages/SettingsLib/res/values-eu/arrays.xml
index 2d3575b..eb678ff 100644
--- a/packages/SettingsLib/res/values-eu/arrays.xml
+++ b/packages/SettingsLib/res/values-eu/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Gaituta baina iragazita"</item>
     <item msgid="2779123106632690576">"Gaituta"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Goiburuan iragazita"</item>
-    <item msgid="4818549483446395865">"A2DP multimedia-paketeak iragazita"</item>
-    <item msgid="8207123990453243311">"RFCOMM kanala iragazita"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desgaituta"</item>
-    <item msgid="5884245882825346396">"Magia"</item>
-    <item msgid="6569400572915342949">"Goiburua"</item>
-    <item msgid="1239386221416967664">"Iragazki osoa"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (lehenetsia)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 82e0eea..02ab192 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmak eta abisuak"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Eman alarmak eta abisuak ezartzeko baimena"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmak eta abisuak"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nEz baduzu ematen baimen hori, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Eman alarmak ezartzeko eta denbora-muga duten ekintzak programatzeko baimena aplikazioari. Hala, aplikazioak atzeko planoan funtzionatuko du, eta litekeena da bateria gehiago kontsumitzea.\n\nBaimen hori ematen ez baduzu, ez dute funtzionatuko aplikazio honen bidez programatutako alarmek eta denbora-muga duten ekintzek."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programazioa, alarma, abisua, erlojua"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Aktibatu"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Aktibatu ez molestatzeko modua"</string>
diff --git a/packages/SettingsLib/res/values-fa/arrays.xml b/packages/SettingsLib/res/values-fa/arrays.xml
index b983bcc..2d9be31 100644
--- a/packages/SettingsLib/res/values-fa/arrays.xml
+++ b/packages/SettingsLib/res/values-fa/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"فیلترشده فعال شده است"</item>
     <item msgid="2779123106632690576">"فعال"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"سرصفحه‌ها فیلتر شد"</item>
-    <item msgid="4818549483446395865">"‏بسته‌های رسانه A2DP فیلتر شد"</item>
-    <item msgid="8207123990453243311">"‏کانال RFCOMM فیلتر شد"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"غیرفعال"</item>
-    <item msgid="5884245882825346396">"جادویی"</item>
-    <item msgid="6569400572915342949">"سرصفحه"</item>
-    <item msgid="1239386221416967664">"فیلتر کامل"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP نسخه ۱.۵ (پیش‌فرض)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fi/arrays.xml b/packages/SettingsLib/res/values-fi/arrays.xml
index 9e3bcd2..d6f002f 100644
--- a/packages/SettingsLib/res/values-fi/arrays.xml
+++ b/packages/SettingsLib/res/values-fi/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Suodatus käytössä"</item>
     <item msgid="2779123106632690576">"Päällä"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Otsikot suodatettu"</item>
-    <item msgid="4818549483446395865">"A2DP-mediapaketit suodatettu"</item>
-    <item msgid="8207123990453243311">"RFCOMM-kanava suodatettu"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Ei käytössä"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Otsikko"</item>
-    <item msgid="1239386221416967664">"Täysi suodatus"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (oletus)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fr-rCA/arrays.xml b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
index 86066b6..6657aa1 100644
--- a/packages/SettingsLib/res/values-fr-rCA/arrays.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtres activés"</item>
     <item msgid="2779123106632690576">"Activé"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"En-têtes filtrés"</item>
-    <item msgid="4818549483446395865">"Paquets multimédias A2DP filtrés"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtré"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Désactivé"</item>
-    <item msgid="5884245882825346396">"Magie"</item>
-    <item msgid="6569400572915342949">"En-tête"</item>
-    <item msgid="1239386221416967664">"Filtre intégral"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (par défaut)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-fr/arrays.xml b/packages/SettingsLib/res/values-fr/arrays.xml
index 5f31ff5..869d88a 100644
--- a/packages/SettingsLib/res/values-fr/arrays.xml
+++ b/packages/SettingsLib/res/values-fr/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Activé et filtré"</item>
     <item msgid="2779123106632690576">"Activé"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"En-têtes filtrés"</item>
-    <item msgid="4818549483446395865">"Paquets multimédias A2DP filtrés"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtré"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Désactivé"</item>
-    <item msgid="5884245882825346396">"Magie"</item>
-    <item msgid="6569400572915342949">"En-tête"</item>
-    <item msgid="1239386221416967664">"Filtre complet"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (par défaut)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-gl/arrays.xml b/packages/SettingsLib/res/values-gl/arrays.xml
index 665851d..3cd7b4b 100644
--- a/packages/SettingsLib/res/values-gl/arrays.xml
+++ b/packages/SettingsLib/res/values-gl/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Está activado o filtrado"</item>
     <item msgid="2779123106632690576">"Activada"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Cabeceiras filtradas"</item>
-    <item msgid="4818549483446395865">"A2DP Media Packets filtrados"</item>
-    <item msgid="8207123990453243311">"Canle RFCOMM filtrada"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desactivado"</item>
-    <item msgid="5884245882825346396">"Maxia"</item>
-    <item msgid="6569400572915342949">"Cabeceira"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predeterminado)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-gu/arrays.xml b/packages/SettingsLib/res/values-gu/arrays.xml
index e373952..f559b80 100644
--- a/packages/SettingsLib/res/values-gu/arrays.xml
+++ b/packages/SettingsLib/res/values-gu/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ફિલ્ટર કરેલ ચાલુ છે"</item>
     <item msgid="2779123106632690576">"ચાલુ છે"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ફિલ્ટર કરેલા હેડર"</item>
-    <item msgid="4818549483446395865">"ફિલ્ટર કરેલા A2DP મીડિયા પૅકેટ"</item>
-    <item msgid="8207123990453243311">"ફિલ્ટર કરેલી RFCOMM ચૅનલ"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"બંધ કર્યું"</item>
-    <item msgid="5884245882825346396">"જાદુ"</item>
-    <item msgid="6569400572915342949">"હેડર"</item>
-    <item msgid="1239386221416967664">"સંપૂર્ણ ફિલ્ટર"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ડિફૉલ્ટ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hi/arrays.xml b/packages/SettingsLib/res/values-hi/arrays.xml
index 356a13c..be88620 100644
--- a/packages/SettingsLib/res/values-hi/arrays.xml
+++ b/packages/SettingsLib/res/values-hi/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"चालू और फ़िल्टर किया गया"</item>
     <item msgid="2779123106632690576">"चालू है"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"हेडर फ़िल्टर किए गए"</item>
-    <item msgid="4818549483446395865">"A2DP मीडिया पैकेट फ़िल्टर किए गए"</item>
-    <item msgid="8207123990453243311">"RFCOMM चैनल फ़िल्टर किए गए"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"बंद है"</item>
-    <item msgid="5884245882825346396">"मैजिक"</item>
-    <item msgid="6569400572915342949">"हेडर"</item>
-    <item msgid="1239386221416967664">"सभी फ़िल्टर"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (डिफ़ॉल्ट)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hr/arrays.xml b/packages/SettingsLib/res/values-hr/arrays.xml
index 812f8d2..5c73ebb 100644
--- a/packages/SettingsLib/res/values-hr/arrays.xml
+++ b/packages/SettingsLib/res/values-hr/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Omogućeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogućeno"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrirana zaglavlja"</item>
-    <item msgid="4818549483446395865">"Filtrirani A2DP medijski paketi"</item>
-    <item msgid="8207123990453243311">"Filtrirani RFCOMM kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Onemogućeno"</item>
-    <item msgid="5884245882825346396">"Čarolija"</item>
-    <item msgid="6569400572915342949">"Zaglavlje"</item>
-    <item msgid="1239386221416967664">"Potpuni filtar"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (zadano)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hu/arrays.xml b/packages/SettingsLib/res/values-hu/arrays.xml
index 9c842f9..500b9fd 100644
--- a/packages/SettingsLib/res/values-hu/arrays.xml
+++ b/packages/SettingsLib/res/values-hu/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Szűrtek engedélyezve"</item>
     <item msgid="2779123106632690576">"Engedélyezve"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Szűrt fejlécek"</item>
-    <item msgid="4818549483446395865">"Szűrt A2DP-médiacsomagok"</item>
-    <item msgid="8207123990453243311">"Szűrt RFCOMM-csatorna"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Kikapcsolva"</item>
-    <item msgid="5884245882825346396">"Mágia"</item>
-    <item msgid="6569400572915342949">"Fejléc"</item>
-    <item msgid="1239386221416967664">"Teljes szűrő"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (alapértelmezett)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-hy/arrays.xml b/packages/SettingsLib/res/values-hy/arrays.xml
index 59351c4..6fd6893 100644
--- a/packages/SettingsLib/res/values-hy/arrays.xml
+++ b/packages/SettingsLib/res/values-hy/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Միացված է զտիչներով"</item>
     <item msgid="2779123106632690576">"Միացված է"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Զտված էջագլուխներ"</item>
-    <item msgid="4818549483446395865">"Զտված A2DP մուլտիմեդիա փաթեթներ"</item>
-    <item msgid="8207123990453243311">"Զտված RFCOMM կապուղի"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Անջատված է"</item>
-    <item msgid="5884245882825346396">"Կախարդանք"</item>
-    <item msgid="6569400572915342949">"Էջագլուխ"</item>
-    <item msgid="1239386221416967664">"Ամբողջական զտիչ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (կանխադրված)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 06e24b9..8257d0e 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Diaktifkan Difilter"</item>
     <item msgid="2779123106632690576">"Diaktifkan"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Header Difilter"</item>
-    <item msgid="4818549483446395865">"Paket Media A2DP Difilter"</item>
-    <item msgid="8207123990453243311">"Saluran RFCOMM Difilter"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Nonaktif"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Filter Lengkap"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-is/arrays.xml b/packages/SettingsLib/res/values-is/arrays.xml
index a87e760..1b114ee 100644
--- a/packages/SettingsLib/res/values-is/arrays.xml
+++ b/packages/SettingsLib/res/values-is/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Kveikt á síuðu"</item>
     <item msgid="2779123106632690576">"Kveikt"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Síaðar fyrirsagnir"</item>
-    <item msgid="4818549483446395865">"Síaðir A2DP-efnispakkar"</item>
-    <item msgid="8207123990453243311">"Síuð RFCOMM-rás"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Slökkt"</item>
-    <item msgid="5884245882825346396">"Töfrar"</item>
-    <item msgid="6569400572915342949">"Haus"</item>
-    <item msgid="1239386221416967664">"Heildarsía"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (sjálfgefið)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-it/arrays.xml b/packages/SettingsLib/res/values-it/arrays.xml
index 18923b6..50eca93 100644
--- a/packages/SettingsLib/res/values-it/arrays.xml
+++ b/packages/SettingsLib/res/values-it/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtro attivo"</item>
     <item msgid="2779123106632690576">"Attiva"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Intestazioni filtrate"</item>
-    <item msgid="4818549483446395865">"Pacchetti multimediali A2DP filtrati"</item>
-    <item msgid="8207123990453243311">"Canale RFCOMM filtrato"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Disattivato"</item>
-    <item msgid="5884245882825346396">"Magia"</item>
-    <item msgid="6569400572915342949">"Intestazione"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (versione predefinita)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-iw/arrays.xml b/packages/SettingsLib/res/values-iw/arrays.xml
index 8e76f2e..02b7751 100644
--- a/packages/SettingsLib/res/values-iw/arrays.xml
+++ b/packages/SettingsLib/res/values-iw/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"המסננים המופעלים"</item>
     <item msgid="2779123106632690576">"מופעל"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"כותרות לאחר סינון"</item>
-    <item msgid="4818549483446395865">"‏מנות מדיה A2DP לאחר סינון"</item>
-    <item msgid="8207123990453243311">"‏ערוצי RFCOMM לאחר סינון"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"בהשבתה"</item>
-    <item msgid="5884245882825346396">"קסם"</item>
-    <item msgid="6569400572915342949">"כותרת"</item>
-    <item msgid="1239386221416967664">"סינון מלא"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP 1.5 (ברירת המחדל)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 47517fe..869fd997 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"有効(フィルタ済み)"</item>
     <item msgid="2779123106632690576">"有効"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ヘッダーのフィルタ"</item>
-    <item msgid="4818549483446395865">"A2DP メディア パケットのフィルタ"</item>
-    <item msgid="8207123990453243311">"RFCOMM チャネルのフィルタ"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"無効"</item>
-    <item msgid="5884245882825346396">"マジック"</item>
-    <item msgid="6569400572915342949">"ヘッダー"</item>
-    <item msgid="1239386221416967664">"フルフィルタ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5(デフォルト)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ka/arrays.xml b/packages/SettingsLib/res/values-ka/arrays.xml
index eceaac7..71a283c 100644
--- a/packages/SettingsLib/res/values-ka/arrays.xml
+++ b/packages/SettingsLib/res/values-ka/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"გაფილტრულის ჩართვა"</item>
     <item msgid="2779123106632690576">"ჩართულია"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"გაფილტრული სათაურები"</item>
-    <item msgid="4818549483446395865">"გაფილტრული A2DP მედია პაკეტები"</item>
-    <item msgid="8207123990453243311">"გაფილტრული RFCOMM არხი"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"გათიშული"</item>
-    <item msgid="5884245882825346396">"მაგია"</item>
-    <item msgid="6569400572915342949">"სათაური"</item>
-    <item msgid="1239386221416967664">"სრული ფილტრი"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ნაგულისხმევი)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-kk/arrays.xml b/packages/SettingsLib/res/values-kk/arrays.xml
index 517b116..ab5e107 100644
--- a/packages/SettingsLib/res/values-kk/arrays.xml
+++ b/packages/SettingsLib/res/values-kk/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Сүзгіленгендері қосулы"</item>
     <item msgid="2779123106632690576">"Қосулы"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Сүзілген тақырыптар"</item>
-    <item msgid="4818549483446395865">"Сүзілген A2DP медиапакеттері"</item>
-    <item msgid="8207123990453243311">"Сүзілген RFCOMM арнасы"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Өшірулі"</item>
-    <item msgid="5884245882825346396">"Сиқыр"</item>
-    <item msgid="6569400572915342949">"Тақырып"</item>
-    <item msgid="1239386221416967664">"Толық сүзгі"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (әдепкі)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-km/arrays.xml b/packages/SettingsLib/res/values-km/arrays.xml
index db99329..bfc9834 100644
--- a/packages/SettingsLib/res/values-km/arrays.xml
+++ b/packages/SettingsLib/res/values-km/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"បានបើក​ការត្រង"</item>
     <item msgid="2779123106632690576">"បាន​បើក"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"បានត្រងក្បាលទំព័រ"</item>
-    <item msgid="4818549483446395865">"បានត្រងកញ្ចប់មេឌៀ A2DP"</item>
-    <item msgid="8207123990453243311">"បានត្រងបណ្ដាញ RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"បានបិទ"</item>
-    <item msgid="5884245882825346396">"វេទមន្ត"</item>
-    <item msgid="6569400572915342949">"ក្បាល​ទំព័រ"</item>
-    <item msgid="1239386221416967664">"តម្រងពេញ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (លំនាំដើម)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-kn/arrays.xml b/packages/SettingsLib/res/values-kn/arrays.xml
index 2bf4ef0..61e2791 100644
--- a/packages/SettingsLib/res/values-kn/arrays.xml
+++ b/packages/SettingsLib/res/values-kn/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ಫಿಲ್ಟರ್ ಮಾಡುವುದನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
     <item msgid="2779123106632690576">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ಶಿರೋಲೇಖಗಳನ್ನು ಫಿಲ್ಟರ್ ಮಾಡಲಾಗಿದೆ"</item>
-    <item msgid="4818549483446395865">"A2DP ಮೀಡಿಯಾ ಪ್ಯಾಕೆಟ್‌ಗಳನ್ನು ಫಿಲ್ಟರ್‌ ಮಾಡಲಾಗಿದೆ"</item>
-    <item msgid="8207123990453243311">"RFCOMM ಚಾನಲ್ ಫಿಲ್ಟರ್‌ ಮಾಡಲಾಗಿದೆ"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
-    <item msgid="5884245882825346396">"ಮ್ಯಾಜಿಕ್"</item>
-    <item msgid="6569400572915342949">"ಶಿರೋಲೇಖ"</item>
-    <item msgid="1239386221416967664">"ಸಂಪೂರ್ಣ ಫಿಲ್ಟರ್"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ಡೀಫಾಲ್ಟ್)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ko/arrays.xml b/packages/SettingsLib/res/values-ko/arrays.xml
index 1a1469f..b4a035a 100644
--- a/packages/SettingsLib/res/values-ko/arrays.xml
+++ b/packages/SettingsLib/res/values-ko/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"필터링 사용 설정됨"</item>
     <item msgid="2779123106632690576">"사용 설정됨"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"헤더 필터링됨"</item>
-    <item msgid="4818549483446395865">"A2DP 미디어 패킷 필터링됨"</item>
-    <item msgid="8207123990453243311">"RFCOMM 채널 필터링됨"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"사용 안함"</item>
-    <item msgid="5884245882825346396">"매직"</item>
-    <item msgid="6569400572915342949">"헤더"</item>
-    <item msgid="1239386221416967664">"전체 필터"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5(기본값)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ky/arrays.xml b/packages/SettingsLib/res/values-ky/arrays.xml
index f59d4d4..657e63e 100644
--- a/packages/SettingsLib/res/values-ky/arrays.xml
+++ b/packages/SettingsLib/res/values-ky/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Чыпкалар иштетилди"</item>
     <item msgid="2779123106632690576">"Иштетилди"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Жогорку колонтитулдар чыпкаланды"</item>
-    <item msgid="4818549483446395865">"A2DP медиа топтомдор чыпкаланды"</item>
-    <item msgid="8207123990453243311">"RFCOMM каналы чыпкаланды"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Өчүрүлдү"</item>
-    <item msgid="5884245882825346396">"Сыйкырдуу"</item>
-    <item msgid="6569400572915342949">"Жогорку колонтитул"</item>
-    <item msgid="1239386221416967664">"Толук чыпка"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Демейки)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lo/arrays.xml b/packages/SettingsLib/res/values-lo/arrays.xml
index 4981273..11688d4 100644
--- a/packages/SettingsLib/res/values-lo/arrays.xml
+++ b/packages/SettingsLib/res/values-lo/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ເປີດການກັ່ນຕອງແລ້ວ"</item>
     <item msgid="2779123106632690576">"ເປີດໃຊ້ແລ້ວ"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ສ່ວນຫົວຖືກກັ່ນຕອງ"</item>
-    <item msgid="4818549483446395865">"ແພັກເກດສື່ A2DP ຖືກກັ່ນຕອງ"</item>
-    <item msgid="8207123990453243311">"ຊ່ອງ RFCOMM ຖືກກັ່ນຕອງ"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ປິດການນຳໃຊ້ແລ້ວ"</item>
-    <item msgid="5884245882825346396">"ເວດມົນ"</item>
-    <item msgid="6569400572915342949">"ສ່ວນຫົວ"</item>
-    <item msgid="1239386221416967664">"ການກັ່ນຕອງແບບເຕັມ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ຄ່າເລີ່ມຕົ້ນ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lt/arrays.xml b/packages/SettingsLib/res/values-lt/arrays.xml
index 15e65e8..6718660 100644
--- a/packages/SettingsLib/res/values-lt/arrays.xml
+++ b/packages/SettingsLib/res/values-lt/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Įgalinta filtruota"</item>
     <item msgid="2779123106632690576">"Įgalinta"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Antraštės išfiltruotos"</item>
-    <item msgid="4818549483446395865">"A2DP medijos paketai išfiltruoti"</item>
-    <item msgid="8207123990453243311">"RFCOMM kanalas išfiltruotas"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Išjungta"</item>
-    <item msgid="5884245882825346396">"Magiškoji eilutė"</item>
-    <item msgid="6569400572915342949">"Antraštė"</item>
-    <item msgid="1239386221416967664">"Visi filtrai"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (numatytoji)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-lv/arrays.xml b/packages/SettingsLib/res/values-lv/arrays.xml
index 47531a0..3e1869a 100644
--- a/packages/SettingsLib/res/values-lv/arrays.xml
+++ b/packages/SettingsLib/res/values-lv/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Iespējot filtrētos"</item>
     <item msgid="2779123106632690576">"Iespējots"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrētas galvenes"</item>
-    <item msgid="4818549483446395865">"Filtrētas A2DP multivides paketes"</item>
-    <item msgid="8207123990453243311">"Filtrēts RFCOMM kanāls"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Atspējots"</item>
-    <item msgid="5884245882825346396">"Pielāgotās virknes"</item>
-    <item msgid="6569400572915342949">"Galvene"</item>
-    <item msgid="1239386221416967664">"Visi filtri"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (noklusējums)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mk/arrays.xml b/packages/SettingsLib/res/values-mk/arrays.xml
index 9d5a5e1..ebf387b 100644
--- a/packages/SettingsLib/res/values-mk/arrays.xml
+++ b/packages/SettingsLib/res/values-mk/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Овозможено е филтрирано"</item>
     <item msgid="2779123106632690576">"Овозможено"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Насловите се филтрирани"</item>
-    <item msgid="4818549483446395865">"A2DP аудиовизуелните пакети се филтрирани"</item>
-    <item msgid="8207123990453243311">"RFCOMM-каналот е филтриран"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Оневозможено"</item>
-    <item msgid="5884245882825346396">"Магија"</item>
-    <item msgid="6569400572915342949">"Заглавие"</item>
-    <item msgid="1239386221416967664">"Целосен филтер"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Стандардна)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ml/arrays.xml b/packages/SettingsLib/res/values-ml/arrays.xml
index f28be85..30adb57 100644
--- a/packages/SettingsLib/res/values-ml/arrays.xml
+++ b/packages/SettingsLib/res/values-ml/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ഫിൽട്ടറിംഗ് പ്രവർത്തനക്ഷമമാക്കി"</item>
     <item msgid="2779123106632690576">"പ്രവർത്തനക്ഷമമാക്കി"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ഹെഡ്ഡറുകൾ ഫിൽട്ടർ ചെയ്‌തു"</item>
-    <item msgid="4818549483446395865">"A2DP മീഡിയാ പാക്കറ്റകൾ ഫിൽട്ടർ ചെയ്‌തു"</item>
-    <item msgid="8207123990453243311">"RFCOMM ചാനൽ ഫിൽട്ടർ ചെയ്‌തു"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"പ്രവർത്തനരഹിതമാക്കി"</item>
-    <item msgid="5884245882825346396">"മാജിക്"</item>
-    <item msgid="6569400572915342949">"ഹെഡ്ഡർ"</item>
-    <item msgid="1239386221416967664">"പൂർണ്ണ ഫിൽട്ടർ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ഡിഫോൾട്ട്)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mn/arrays.xml b/packages/SettingsLib/res/values-mn/arrays.xml
index d3c344e..d03fcd6 100644
--- a/packages/SettingsLib/res/values-mn/arrays.xml
+++ b/packages/SettingsLib/res/values-mn/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Идэвхжүүлсэн Шүүсэн"</item>
     <item msgid="2779123106632690576">"Идэвхжүүлсэн"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Толгой хэсгийг шүүсэн"</item>
-    <item msgid="4818549483446395865">"A2DP Медиа пакетыг шүүсэн"</item>
-    <item msgid="8207123990453243311">"RFCOMM сувгийг шүүсэн"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Идэвхгүй болгосон"</item>
-    <item msgid="5884245882825346396">"Ид шид"</item>
-    <item msgid="6569400572915342949">"Толгой хэсэг"</item>
-    <item msgid="1239386221416967664">"Бүтэн шүүлтүүр"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Өгөгдмөл)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-mr/arrays.xml b/packages/SettingsLib/res/values-mr/arrays.xml
index 093e36b..68eff75 100644
--- a/packages/SettingsLib/res/values-mr/arrays.xml
+++ b/packages/SettingsLib/res/values-mr/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"फिल्टर केलेले सुरू केले"</item>
     <item msgid="2779123106632690576">"सुरू केले"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"फिल्टर केलेले हेडर"</item>
-    <item msgid="4818549483446395865">"फिल्टर केलेली A2DP मीडिया पॅकेट"</item>
-    <item msgid="8207123990453243311">"फिल्टर केलेली RFCOMM चॅनल"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"बंद केले"</item>
-    <item msgid="5884245882825346396">"मॅजिक"</item>
-    <item msgid="6569400572915342949">"हेडर"</item>
-    <item msgid="1239386221416967664">"पूर्ण फिल्टर"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (डीफॉल्ट)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ms/arrays.xml b/packages/SettingsLib/res/values-ms/arrays.xml
index 1daa579..efdd879 100644
--- a/packages/SettingsLib/res/values-ms/arrays.xml
+++ b/packages/SettingsLib/res/values-ms/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Didayakan Ditapis"</item>
     <item msgid="2779123106632690576">"Didayakan"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Pengepala Ditapis"</item>
-    <item msgid="4818549483446395865">"Paket Media A2DP Ditapis"</item>
-    <item msgid="8207123990453243311">"Saluran RFCOMM Ditapis"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Dilumpuhkan"</item>
-    <item msgid="5884245882825346396">"Magik"</item>
-    <item msgid="6569400572915342949">"Pengepala"</item>
-    <item msgid="1239386221416967664">"Penapis Penuh"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Lalai)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-my/arrays.xml b/packages/SettingsLib/res/values-my/arrays.xml
index dbca299..4d0b792 100644
--- a/packages/SettingsLib/res/values-my/arrays.xml
+++ b/packages/SettingsLib/res/values-my/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"စစ်ထုတ်ထားသည်များကို ဖွင့်ထားသည်"</item>
     <item msgid="2779123106632690576">"ဖွင့်ထားသည်"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"စစ်ထုတ်ထားသော ခေါင်းစီးများ"</item>
-    <item msgid="4818549483446395865">"စစ်ထုတ်ထားသော A2DP မီဒီယာအတွဲများ"</item>
-    <item msgid="8207123990453243311">"စစ်ထုတ်ထားသော RFCOMM ချန်နယ်"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ပိတ်ထားသည်"</item>
-    <item msgid="5884245882825346396">"ပဉ္စလက်"</item>
-    <item msgid="6569400572915342949">"ခေါင်းစီး"</item>
-    <item msgid="1239386221416967664">"စစ်ထုတ်မှုအပြည့်"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (မူလ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-nb/arrays.xml b/packages/SettingsLib/res/values-nb/arrays.xml
index 35c4cdd..9293bdad 100644
--- a/packages/SettingsLib/res/values-nb/arrays.xml
+++ b/packages/SettingsLib/res/values-nb/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrering er slått på"</item>
     <item msgid="2779123106632690576">"Slått på"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrert topptekst"</item>
-    <item msgid="4818549483446395865">"Filtrerte A2DP-mediepakker"</item>
-    <item msgid="8207123990453243311">"Filtrert RFCOMM-kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Slått av"</item>
-    <item msgid="5884245882825346396">"Magi"</item>
-    <item msgid="6569400572915342949">"Topptekst"</item>
-    <item msgid="1239386221416967664">"Fullt filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ne/arrays.xml b/packages/SettingsLib/res/values-ne/arrays.xml
index 76652cd..29a7c60 100644
--- a/packages/SettingsLib/res/values-ne/arrays.xml
+++ b/packages/SettingsLib/res/values-ne/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"फिल्टर सक्षम पारियो"</item>
     <item msgid="2779123106632690576">"सक्षम पारिएको छ"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"हेडरहरू फिल्टर गरिए"</item>
-    <item msgid="4818549483446395865">"A2DP मिडिया प्याकेटहरू फिल्टर गरिए"</item>
-    <item msgid="8207123990453243311">"RFCOMM च्यानल फिल्टर गरियो"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"अफ गरियो"</item>
-    <item msgid="5884245882825346396">"म्याजिक"</item>
-    <item msgid="6569400572915342949">"हेडर"</item>
-    <item msgid="1239386221416967664">"फुल फिल्टर"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP १.५ (डिफल्ट)"</item>
     <item msgid="1637054408779685086">"AVRCP १.३"</item>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index ae7e8b3..831ed2f 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -520,7 +520,7 @@
     <string name="okay" msgid="949938843324579502">"ठिक छ"</string>
     <string name="done" msgid="381184316122520313">"सम्पन्न भयो"</string>
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"अलार्म र रिमाइन्डरहरू"</string>
-    <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म तथा रिमाइन्डर सेट गर्न दिइयोस्"</string>
+    <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"अलार्म तथा रिमाइन्डर सेट गर्ने अनुमति दिनुहोस्"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"अलार्म तथा रिमाइन्डर"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"यो एपलाई अलार्म सेट गर्ने र समयमै पूरा गर्नु पर्ने कारबाहीहरूको रुटिन बनाउने अनुमति दिनुहोस्। यो अनुमति दिइएको छ भने यो एप ब्याकग्राउन्डमा चल्छ र धेरै ब्याट्री खपत हुन्छ।\n\nयो अनुमति दिइएको छैन भने सेट गरिएका अलार्म बज्दैनन् र यो एपले तय गरेका गतिविधि चल्दैनन्।"</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"समयतालिका, अलार्म, रिमाइन्डर, घडी"</string>
diff --git a/packages/SettingsLib/res/values-nl/arrays.xml b/packages/SettingsLib/res/values-nl/arrays.xml
index 2ecfbd8..460302c 100644
--- a/packages/SettingsLib/res/values-nl/arrays.xml
+++ b/packages/SettingsLib/res/values-nl/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Gefilterd staat aan"</item>
     <item msgid="2779123106632690576">"Aangezet"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Headers gefilterd"</item>
-    <item msgid="4818549483446395865">"A2DP-mediapakketten gefilterd"</item>
-    <item msgid="8207123990453243311">"RFCOMM-kanaal gefilterd"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Uitgezet"</item>
-    <item msgid="5884245882825346396">"Magie"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Volledig filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standaard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-or/arrays.xml b/packages/SettingsLib/res/values-or/arrays.xml
index 5f48344..439bd72 100644
--- a/packages/SettingsLib/res/values-or/arrays.xml
+++ b/packages/SettingsLib/res/values-or/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ଫିଲ୍ଟର୍‌କୁ ସକ୍ଷମ କରାଯାଇଛି"</item>
     <item msgid="2779123106632690576">"ସକ୍ଷମ କରାଯାଇଛି"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ହେଡରଗୁଡ଼ିକୁ ଫିଲ୍ଟର କରାଯାଇଛି"</item>
-    <item msgid="4818549483446395865">"A2DP ମିଡିଆ ପେକେଟ ଫିଲ୍ଟର କରାଯାଇଛି"</item>
-    <item msgid="8207123990453243311">"RFCOMM ଚେନେଲ ଫିଲ୍ଟର କରାଯାଇଛି"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ଅକ୍ଷମ କରାଯାଇଛି"</item>
-    <item msgid="5884245882825346396">"ମେଜିକ"</item>
-    <item msgid="6569400572915342949">"ହେଡର"</item>
-    <item msgid="1239386221416967664">"ସମ୍ପୂର୍ଣ୍ଣ ଫିଲ୍ଟର"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ଡିଫଲ୍ଟ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pa/arrays.xml b/packages/SettingsLib/res/values-pa/arrays.xml
index d8b1c7e..f4bfcd1 100644
--- a/packages/SettingsLib/res/values-pa/arrays.xml
+++ b/packages/SettingsLib/res/values-pa/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ਫਿਲਟਰ ਕੀਤਿਆਂ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</item>
     <item msgid="2779123106632690576">"ਚਾਲੂ"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ਸਿਰਲੇਖ ਫਿਲਟਰ ਕੀਤੇ ਗਏ"</item>
-    <item msgid="4818549483446395865">"A2DP ਮੀਡੀਆ ਪੈਕੇਟ ਫਿਲਟਰ ਕੀਤੇ ਗਏ"</item>
-    <item msgid="8207123990453243311">"RFCOMM ਚੈਨਲ ਫਿਲਟਰ ਕੀਤੇ ਗਏ"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ਬੰਦ ਹੈ"</item>
-    <item msgid="5884245882825346396">"ਜਾਦੂ"</item>
-    <item msgid="6569400572915342949">"ਸਿਰਲੇਖ"</item>
-    <item msgid="1239386221416967664">"ਸਭ ਫਿਲਟਰ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ਪੂਰਵ-ਨਿਰਧਾਰਿਤ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pl/arrays.xml b/packages/SettingsLib/res/values-pl/arrays.xml
index 9659acb..a305a65 100644
--- a/packages/SettingsLib/res/values-pl/arrays.xml
+++ b/packages/SettingsLib/res/values-pl/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrowanie włączone"</item>
     <item msgid="2779123106632690576">"Włączono"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Przefiltrowane nagłówki"</item>
-    <item msgid="4818549483446395865">"Przefiltrowane pakiety multimediów A2DP"</item>
-    <item msgid="8207123990453243311">"Przefiltrowany kanał RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Wyłączono"</item>
-    <item msgid="5884245882825346396">"Magia"</item>
-    <item msgid="6569400572915342949">"Nagłówek"</item>
-    <item msgid="1239386221416967664">"Pełny filtr"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (domyślnie)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 84aa66a..ddff92c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmy i przypomnienia"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Zezwalaj na ustawianie alarmów i przypomnień"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmy i przypomnienia"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwól na ustawianie alarmów i planowanie innych działań, w przypadku których czas jest istotny. Dzięki temu aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tych uprawnień, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Zezwalaj tej aplikacji na ustawianie alarmów i planowanie działań, w przypadku których czas jest istotny. Aplikacja będzie mogła działać w tle, co może zwiększyć wykorzystanie baterii.\n\nJeśli nie włączysz tego uprawnienia, istniejące alarmy i zaplanowane wydarzenia z tej aplikacji nie będą działać."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"harmonogram, alarm, przypomnienie, zegar"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Włącz"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Włącz tryb Nie przeszkadzać"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/arrays.xml b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
index 0bff6c7..eff0922 100644
--- a/packages/SettingsLib/res/values-pt-rBR/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtro ativado"</item>
     <item msgid="2779123106632690576">"Ativado"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
-    <item msgid="4818549483446395865">"Pacotes de mídia A2DP filtrados"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desativado"</item>
-    <item msgid="5884245882825346396">"Mágica"</item>
-    <item msgid="6569400572915342949">"Cabeçalho"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (padrão)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 168207d..3a48c3d 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/arrays.xml b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
index b134be6..0553aac 100644
--- a/packages/SettingsLib/res/values-pt-rPT/arrays.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrado ativado"</item>
     <item msgid="2779123106632690576">"Ativado"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
-    <item msgid="4818549483446395865">"Pacotes de multimédia A2DP filtrados"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desativado"</item>
-    <item msgid="5884245882825346396">"Magia"</item>
-    <item msgid="6569400572915342949">"Cabeçalho"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predefinição)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt/arrays.xml b/packages/SettingsLib/res/values-pt/arrays.xml
index 0bff6c7..eff0922 100644
--- a/packages/SettingsLib/res/values-pt/arrays.xml
+++ b/packages/SettingsLib/res/values-pt/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtro ativado"</item>
     <item msgid="2779123106632690576">"Ativado"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Cabeçalhos filtrados"</item>
-    <item msgid="4818549483446395865">"Pacotes de mídia A2DP filtrados"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrado"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Desativado"</item>
-    <item msgid="5884245882825346396">"Mágica"</item>
-    <item msgid="6569400572915342949">"Cabeçalho"</item>
-    <item msgid="1239386221416967664">"Filtro completo"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (padrão)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 168207d..3a48c3d 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmes e lembretes"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Autorizar a definição de alarmes e lembretes"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmes e lembretes"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações mais imediatas. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permitir que o app defina alarmes e programe ações com hora marcada. Essa opção autoriza o app a ser executado em segundo plano, o que pode consumir mais bateria.\n\nSe a permissão for desativada, os alarmes e eventos programados pelo app não funcionarão."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programar, alarme, lembrete, relógio"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Ativar"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Ativar o Não perturbe"</string>
diff --git a/packages/SettingsLib/res/values-ro/arrays.xml b/packages/SettingsLib/res/values-ro/arrays.xml
index 8c7ffb2..303d669 100644
--- a/packages/SettingsLib/res/values-ro/arrays.xml
+++ b/packages/SettingsLib/res/values-ro/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Este activat Filtrat"</item>
     <item msgid="2779123106632690576">"Activat"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Anteturi filtrate"</item>
-    <item msgid="4818549483446395865">"Pachete media A2DP filtrate"</item>
-    <item msgid="8207123990453243311">"Canal RFCOMM filtrat"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Dezactivat"</item>
-    <item msgid="5884245882825346396">"Magie"</item>
-    <item msgid="6569400572915342949">"Antet"</item>
-    <item msgid="1239386221416967664">"Filtru complet"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (prestabilit)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index dba7507..e9afb3d 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarme și mementouri"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Permite setarea pentru alarme și mementouri"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarme și mementouri"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să stabilească alarme și să planifice acțiuni dependente de timp. Astfel, aplicația poate să ruleze în fundal, fapt care ar putea consuma mai multă baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Permite acestei aplicații să seteze alarme și să planifice acțiuni care trebuie realizate în timp scurt. Astfel, aplicația poate să ruleze în fundal, ceea ce ar putea crește consumul de baterie.\n\nDacă permisiunea este dezactivată, alarmele și evenimentele dependente de timp planificate de aplicație nu vor funcționa."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"programare, alarmă, memento, ceas"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Activează"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Activează Nu deranja"</string>
diff --git a/packages/SettingsLib/res/values-ru/arrays.xml b/packages/SettingsLib/res/values-ru/arrays.xml
index 1df0435..4772df98 100644
--- a/packages/SettingsLib/res/values-ru/arrays.xml
+++ b/packages/SettingsLib/res/values-ru/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Включены фильтры"</item>
     <item msgid="2779123106632690576">"Включено"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Применен фильтр по заголовкам"</item>
-    <item msgid="4818549483446395865">"Применен фильтр по медиапакетам A2DP"</item>
-    <item msgid="8207123990453243311">"Применен фильтр по каналу RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Отключено"</item>
-    <item msgid="5884245882825346396">"Специальный параметр"</item>
-    <item msgid="6569400572915342949">"Заголовок"</item>
-    <item msgid="1239386221416967664">"Общий фильтр"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (по умолчанию)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 76d163c..16788c3 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -522,7 +522,7 @@
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Будильники и напоминания"</string>
     <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Разрешить установку будильников и напоминаний"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Будильники и напоминания"</string>
-    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Если вы разрешите этому приложению устанавливать будильники и планировать на определенное время действия, оно будет работать в фоновом режиме. В таком случае заряд батареи может расходоваться быстрее.\n\nЕсли отключить эту настройку, текущие будильники и созданные приложением мероприятия перестанут запускаться."</string>
+    <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Вы можете разрешить этому приложению устанавливать будильники и планировать запуск действий в определенное время. В этом случае оно будет работать в фоновом режиме и быстрее расходовать заряд батареи.\n\nЕсли отключить это разрешение, текущие будильники и созданные приложением события перестанут запускаться."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"установить, будильник, напоминание, часы"</string>
     <string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Включить"</string>
     <string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Включите режим \"Не беспокоить\""</string>
diff --git a/packages/SettingsLib/res/values-si/arrays.xml b/packages/SettingsLib/res/values-si/arrays.xml
index b516ce6..8de6a71 100644
--- a/packages/SettingsLib/res/values-si/arrays.xml
+++ b/packages/SettingsLib/res/values-si/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"සබල පෙරහන් කළ"</item>
     <item msgid="2779123106632690576">"සබලයි"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ශීර්ෂයන් පෙරන ලදි"</item>
-    <item msgid="4818549483446395865">"A2DP මාධ්‍ය පැකට් පෙරන ලදි"</item>
-    <item msgid="8207123990453243311">"RFCOMM නාලිකාව පෙරන ලදි"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"අබලයි"</item>
-    <item msgid="5884245882825346396">"මැජික්"</item>
-    <item msgid="6569400572915342949">"ශීර්ෂකය"</item>
-    <item msgid="1239386221416967664">"පූර්ණ පෙරහන"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (පෙරනිමි)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sk/arrays.xml b/packages/SettingsLib/res/values-sk/arrays.xml
index 35c4518..f15dfb7 100644
--- a/packages/SettingsLib/res/values-sk/arrays.xml
+++ b/packages/SettingsLib/res/values-sk/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Aktivované filtrované"</item>
     <item msgid="2779123106632690576">"Aktivované"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Hlavičky sú filtrované"</item>
-    <item msgid="4818549483446395865">"Balíky A2DP Media sú filtrované"</item>
-    <item msgid="8207123990453243311">"Kanál RFCOMM je filtrovaný"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Deaktivované"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Hlavička"</item>
-    <item msgid="1239386221416967664">"Úplný filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (predvolené)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sl/arrays.xml b/packages/SettingsLib/res/values-sl/arrays.xml
index 12442a4..9ef852c 100644
--- a/packages/SettingsLib/res/values-sl/arrays.xml
+++ b/packages/SettingsLib/res/values-sl/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Omogočeno filtrirano"</item>
     <item msgid="2779123106632690576">"Omogočeno"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Glave so filtrirane"</item>
-    <item msgid="4818549483446395865">"Predstavnostni paketi A2DP so filtrirani"</item>
-    <item msgid="8207123990453243311">"Kanal RFCOMM je filtriran"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Onemogočeno"</item>
-    <item msgid="5884245882825346396">"Čarovnija"</item>
-    <item msgid="6569400572915342949">"Glava"</item>
-    <item msgid="1239386221416967664">"Polni filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (privzeto)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sq/arrays.xml b/packages/SettingsLib/res/values-sq/arrays.xml
index 742a86a..89a316d 100644
--- a/packages/SettingsLib/res/values-sq/arrays.xml
+++ b/packages/SettingsLib/res/values-sq/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Të aktivizuara të filtruara"</item>
     <item msgid="2779123106632690576">"Aktiv"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Titujt e filtruar"</item>
-    <item msgid="4818549483446395865">"Paketat e medias A2DP të filtruara"</item>
-    <item msgid="8207123990453243311">"Kanalet e RFCOMM të filtruara"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Joaktiv"</item>
-    <item msgid="5884245882825346396">"Magji"</item>
-    <item msgid="6569400572915342949">"Titulli"</item>
-    <item msgid="1239386221416967664">"Filtri i plotë"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (I parazgjedhur)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sr/arrays.xml b/packages/SettingsLib/res/values-sr/arrays.xml
index a338142..e76820e 100644
--- a/packages/SettingsLib/res/values-sr/arrays.xml
+++ b/packages/SettingsLib/res/values-sr/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Омогућено филтрирано"</item>
     <item msgid="2779123106632690576">"Омогућено"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Филтрирана заглавља"</item>
-    <item msgid="4818549483446395865">"Филтрирани A2DP медијски пакети"</item>
-    <item msgid="8207123990453243311">"Филтрирани RFCOMM канал"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Онемогућено"</item>
-    <item msgid="5884245882825346396">"Магија"</item>
-    <item msgid="6569400572915342949">"Заглавље"</item>
-    <item msgid="1239386221416967664">"Потпуни филтер"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (подразумевано)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sv/arrays.xml b/packages/SettingsLib/res/values-sv/arrays.xml
index a31c155..391f603 100644
--- a/packages/SettingsLib/res/values-sv/arrays.xml
+++ b/packages/SettingsLib/res/values-sv/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrering har aktiverats"</item>
     <item msgid="2779123106632690576">"Aktiverad"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Filtrerade rubriker"</item>
-    <item msgid="4818549483446395865">"Filtrerade A2DP-mediapaket"</item>
-    <item msgid="8207123990453243311">"Filtrerad RFCOMM-kanal"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Inaktiverad"</item>
-    <item msgid="5884245882825346396">"Magi"</item>
-    <item msgid="6569400572915342949">"Rubrik"</item>
-    <item msgid="1239386221416967664">"Fullständigt filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (standard)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-sw/arrays.xml b/packages/SettingsLib/res/values-sw/arrays.xml
index 8daf092..1a33b6e4 100644
--- a/packages/SettingsLib/res/values-sw/arrays.xml
+++ b/packages/SettingsLib/res/values-sw/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Vichujio Vilivyowekwa"</item>
     <item msgid="2779123106632690576">"Imewashwa"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Vijajuu Vimechujwa"</item>
-    <item msgid="4818549483446395865">"Kifurushi cha Maelezo cha A2DP Kimechujwa"</item>
-    <item msgid="8207123990453243311">"Kituo cha RFCOMM Kimechujwa"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Kimezimwa"</item>
-    <item msgid="5884245882825346396">"Kiinimacho"</item>
-    <item msgid="6569400572915342949">"Kijajuu"</item>
-    <item msgid="1239386221416967664">"Kichujio Kamili"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Chaguomsingi)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ta/arrays.xml b/packages/SettingsLib/res/values-ta/arrays.xml
index 8f2fe7e..23eb242 100644
--- a/packages/SettingsLib/res/values-ta/arrays.xml
+++ b/packages/SettingsLib/res/values-ta/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"இயக்கப்பட்டு வடிகட்டப்பட்டது"</item>
     <item msgid="2779123106632690576">"இயக்கப்பட்டது"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"வடிகட்டப்பட்ட தலைப்புப்பகுதிகள்"</item>
-    <item msgid="4818549483446395865">"வடிகட்டப்பட்ட A2DP மீடியா பேக்கெட்டுகள்"</item>
-    <item msgid="8207123990453243311">"வடிகட்டப்பட்ட RFCOMM சேனல்"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"முடக்கப்பட்டுள்ளது"</item>
-    <item msgid="5884245882825346396">"மேஜிக்"</item>
-    <item msgid="6569400572915342949">"தலைப்புப்பகுதி"</item>
-    <item msgid="1239386221416967664">"முழு வடிப்பான்"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (இயல்பு)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml
index 4b07f37..0f62c1d 100644
--- a/packages/SettingsLib/res/values-te/arrays.xml
+++ b/packages/SettingsLib/res/values-te/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"ప్రారంభించబడింది ఫిల్టర్ చేయబడింది"</item>
     <item msgid="2779123106632690576">"ప్రారంభించబడింది"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"హెడర్‌లు ఫిల్టర్ చేయబడ్డాయి"</item>
-    <item msgid="4818549483446395865">"A2DP మీడియా ప్యాకెట్‌లు ఫిల్టర్ చేయబడ్డాయి"</item>
-    <item msgid="8207123990453243311">"RFCOMM ఛానెల్ ఫిల్టర్ చేయబడింది"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"డిజేబుల్ చేయబడింది"</item>
-    <item msgid="5884245882825346396">"మ్యాజిక్"</item>
-    <item msgid="6569400572915342949">"హెడర్"</item>
-    <item msgid="1239386221416967664">"పూర్తి ఫిల్టర్"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.4 (ఆటోమేటిక్ సెట్టింగ్)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml
index be8dd8b..8d98cdb 100644
--- a/packages/SettingsLib/res/values-th/arrays.xml
+++ b/packages/SettingsLib/res/values-th/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"เปิดใช้รายการที่กรอง"</item>
     <item msgid="2779123106632690576">"เปิดใช้"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ส่วนหัวที่กรอง"</item>
-    <item msgid="4818549483446395865">"แพ็กเก็ตสื่อ A2DP ที่กรอง"</item>
-    <item msgid="8207123990453243311">"แชแนล RFCOMM ที่กรอง"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"ปิดใช้"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"ส่วนหัว"</item>
-    <item msgid="1239386221416967664">"ตัวกรองแบบเต็ม"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (ค่าเริ่มต้น)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tl/arrays.xml b/packages/SettingsLib/res/values-tl/arrays.xml
index 9b4ae0e..ed47d32 100644
--- a/packages/SettingsLib/res/values-tl/arrays.xml
+++ b/packages/SettingsLib/res/values-tl/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Na-enable Na-filter"</item>
     <item msgid="2779123106632690576">"Naka-enable"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Mga Na-filter na Header"</item>
-    <item msgid="4818549483446395865">"Mga Na-filter na A2DP Media Packet"</item>
-    <item msgid="8207123990453243311">"Mga Na-filter na RFCOMM Channel"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Naka-disable"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"Header"</item>
-    <item msgid="1239386221416967664">"Kumpletong Filter"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Default)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tr/arrays.xml b/packages/SettingsLib/res/values-tr/arrays.xml
index 57c9935..45580f5 100644
--- a/packages/SettingsLib/res/values-tr/arrays.xml
+++ b/packages/SettingsLib/res/values-tr/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Etkin Filtrelenmiş"</item>
     <item msgid="2779123106632690576">"Etkin"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Başlıklar Filtrelendi"</item>
-    <item msgid="4818549483446395865">"A2DP Medya Paketleri Filtrelendi"</item>
-    <item msgid="8207123990453243311">"RFCOMM Kanalı Filtrelendi"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Devre dışı"</item>
-    <item msgid="5884245882825346396">"Sihir"</item>
-    <item msgid="6569400572915342949">"Başlık"</item>
-    <item msgid="1239386221416967664">"Tam Filtre"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Varsayılan)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 86d53e7..1f56170 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -520,7 +520,7 @@
     <string name="okay" msgid="949938843324579502">"Tamam"</string>
     <string name="done" msgid="381184316122520313">"Bitti"</string>
     <string name="alarms_and_reminders_label" msgid="6918395649731424294">"Alarmlar ve hatırlatıcılar"</string>
-    <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlanmasına izin ver"</string>
+    <string name="alarms_and_reminders_switch_title" msgid="4939393911531826222">"Alarm ve hatırlatıcı ayarlamasına izin ver"</string>
     <string name="alarms_and_reminders_title" msgid="8819933264635406032">"Alarmlar ve hatırlatıcılar"</string>
     <string name="alarms_and_reminders_footer_title" msgid="6302587438389079695">"Bu uygulamanın alarm kurmasına ve zamana bağlı işlemler programlamasına izin verin. Bu izin, uygulamanın arka planda çalışmasına olanak sağlayarak daha fazla pil harcanmasına neden olabilir.\n\nBu izin verilmezse bu uygulama tarafından programlanmış mevcut alarmlar ve zamana bağlı etkinlikler çalışmaz."</string>
     <string name="keywords_alarms_and_reminders" msgid="6633360095891110611">"program, alarm, hatırlatıcı, saat"</string>
diff --git a/packages/SettingsLib/res/values-uk/arrays.xml b/packages/SettingsLib/res/values-uk/arrays.xml
index 53bbb87..f97452c 100644
--- a/packages/SettingsLib/res/values-uk/arrays.xml
+++ b/packages/SettingsLib/res/values-uk/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Увімкнено з фільтром"</item>
     <item msgid="2779123106632690576">"Увімкнено"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Фільтрування за заголовками"</item>
-    <item msgid="4818549483446395865">"Фільтрування за пакетами медіаданих A2DP"</item>
-    <item msgid="8207123990453243311">"Фільтрування за каналом RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Вимкнено"</item>
-    <item msgid="5884245882825346396">"Магія"</item>
-    <item msgid="6569400572915342949">"Заголовок"</item>
-    <item msgid="1239386221416967664">"Повний фільтр"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (за умовчанням)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-ur/arrays.xml b/packages/SettingsLib/res/values-ur/arrays.xml
index 5f82062..74af322 100644
--- a/packages/SettingsLib/res/values-ur/arrays.xml
+++ b/packages/SettingsLib/res/values-ur/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"فعال کردہ فلٹر کردہ"</item>
     <item msgid="2779123106632690576">"فعال"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"ہیڈرز فلٹر کئے گئے"</item>
-    <item msgid="4818549483446395865">"‏A2DP میڈیا پیکٹ فلٹر کیے گئے"</item>
-    <item msgid="8207123990453243311">"‏RFCOMM چینل فلٹر کیا گیا"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"غیر فعال"</item>
-    <item msgid="5884245882825346396">"جادو"</item>
-    <item msgid="6569400572915342949">"ہیڈر"</item>
-    <item msgid="1239386221416967664">"مکمل فلٹر"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"‏AVRCP 1.5 (ڈیفالٹ)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml
index dc7e6cd..3e53ae6 100644
--- a/packages/SettingsLib/res/values-uz/arrays.xml
+++ b/packages/SettingsLib/res/values-uz/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Filtrlar yoniq"</item>
     <item msgid="2779123106632690576">"Yoniq"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Sarlavhalar filtrlandi"</item>
-    <item msgid="4818549483446395865">"A2DP media paketlar filtrlandi"</item>
-    <item msgid="8207123990453243311">"RFCOMM kanali filtrlandi"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Faolsizlantirilgan"</item>
-    <item msgid="5884245882825346396">"Sehr"</item>
-    <item msgid="6569400572915342949">"Sarlavha"</item>
-    <item msgid="1239386221416967664">"Toʻliq filtrlash"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (asosiy)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-vi/arrays.xml b/packages/SettingsLib/res/values-vi/arrays.xml
index 18e6c57..649cb5c 100644
--- a/packages/SettingsLib/res/values-vi/arrays.xml
+++ b/packages/SettingsLib/res/values-vi/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Đã bật và lọc"</item>
     <item msgid="2779123106632690576">"Đã bật"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Đã lọc tiêu đề"</item>
-    <item msgid="4818549483446395865">"Đã lọc gói nội dung nghe nhìn A2DP"</item>
-    <item msgid="8207123990453243311">"Đã lọc kênh RFCOMM"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Đã tắt"</item>
-    <item msgid="5884245882825346396">"Ảo thuật"</item>
-    <item msgid="6569400572915342949">"Tiêu đề"</item>
-    <item msgid="1239386221416967664">"Bộ lọc đầy đủ"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (Mặc định)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rCN/arrays.xml b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
index 0d76e6f..13941af 100644
--- a/packages/SettingsLib/res/values-zh-rCN/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"已启用“已过滤”"</item>
     <item msgid="2779123106632690576">"已启用"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"已过滤标题"</item>
-    <item msgid="4818549483446395865">"已过滤 A2DP 媒体数据包"</item>
-    <item msgid="8207123990453243311">"已过滤 RFCOMM 通道"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"已停用"</item>
-    <item msgid="5884245882825346396">"魔术"</item>
-    <item msgid="6569400572915342949">"标题"</item>
-    <item msgid="1239386221416967664">"完整过滤器"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5(默认)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rHK/arrays.xml b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
index c30e9f7..9b359ed 100644
--- a/packages/SettingsLib/res/values-zh-rHK/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"已啟用篩選"</item>
     <item msgid="2779123106632690576">"已啟用"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"已篩選標題"</item>
-    <item msgid="4818549483446395865">"已篩選 A2DP 媒體封包"</item>
-    <item msgid="8207123990453243311">"已篩選 RFCOMM 頻道"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"已停用"</item>
-    <item msgid="5884245882825346396">"Magic"</item>
-    <item msgid="6569400572915342949">"標題"</item>
-    <item msgid="1239386221416967664">"完整篩選器"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
index c6073f0..00362d8 100644
--- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"已啟用篩選結果"</item>
     <item msgid="2779123106632690576">"已啟用"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"已篩選標頭"</item>
-    <item msgid="4818549483446395865">"已篩選 A2DP 媒體封包"</item>
-    <item msgid="8207123990453243311">"已篩選 RFCOMM 管道"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"已停用"</item>
-    <item msgid="5884245882825346396">"按偏好排序"</item>
-    <item msgid="6569400572915342949">"標頭"</item>
-    <item msgid="1239386221416967664">"完整篩選器"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"AVRCP 1.5 (預設)"</item>
     <item msgid="1637054408779685086">"AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 8bfbd7a..588c4f4 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -230,7 +230,7 @@
     <string name="adb_wireless_error" msgid="721958772149779856">"錯誤"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"無線偵錯"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"如要查看並使用可用的裝置,請開啟無線偵錯功能"</string>
-    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR 圖碼配對裝置"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR code 配對裝置"</string>
     <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"使用 QR code 掃描器配對新裝置"</string>
     <string name="adb_pair_method_code_title" msgid="1122590300445142904">"使用配對碼配對裝置"</string>
     <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"使用六位數的配對碼配對新裝置"</string>
diff --git a/packages/SettingsLib/res/values-zu/arrays.xml b/packages/SettingsLib/res/values-zu/arrays.xml
index 8b23bbb..ac3cb02 100644
--- a/packages/SettingsLib/res/values-zu/arrays.xml
+++ b/packages/SettingsLib/res/values-zu/arrays.xml
@@ -63,17 +63,13 @@
     <item msgid="6336372935919715515">"Okuhlungiwe okunikwe amandla"</item>
     <item msgid="2779123106632690576">"Kunikwe amandla"</item>
   </string-array>
-  <string-array name="bt_hci_snoop_log_filters_entries">
-    <item msgid="5118179698172834473">"Izihloko Zihlungiwe"</item>
-    <item msgid="4818549483446395865">"I-A2DP Media Packets Ihlungiwe"</item>
-    <item msgid="8207123990453243311">"Isiteshi se-RFCOMM Sihlungiwe"</item>
-  </string-array>
-  <string-array name="bt_hci_snoop_log_profile_filter_entries">
-    <item msgid="6348114316510677939">"Kukhutshaziwe"</item>
-    <item msgid="5884245882825346396">"Umlingo"</item>
-    <item msgid="6569400572915342949">"Unhlokweni"</item>
-    <item msgid="1239386221416967664">"Isihlungi Esigcwele"</item>
-  </string-array>
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:0 (195768089203590086) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:1 (2776218217644557831) -->
+    <!-- no translation found for bt_hci_snoop_log_filters_entries:2 (8163235976612675092) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:0 (3961868665260627524) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:1 (2505973306504851132) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:2 (5883011000629613855) -->
+    <!-- no translation found for bt_hci_snoop_log_profile_filter_entries:3 (1051534112762023603) -->
   <string-array name="bluetooth_avrcp_versions">
     <item msgid="6603880723315236832">"I-AVRCP 1.5 (Okuzenzakalelayo)"</item>
     <item msgid="1637054408779685086">"I-AVRCP 1.3"</item>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index 888b09f..e846480 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -575,9 +575,15 @@
 
     /** Get the corresponding adaptive icon drawable. */
     public static Drawable getBadgedIcon(Context context, Drawable icon, UserHandle user) {
+        UserManager um = context.getSystemService(UserManager.class);
+        boolean isClone = um.getProfiles(user.getIdentifier()).stream()
+                .anyMatch(profile ->
+                        profile.isCloneProfile() && profile.id == user.getIdentifier());
         try (IconFactory iconFactory = IconFactory.obtain(context)) {
             return iconFactory
-                    .createBadgedIconBitmap(icon, new IconOptions().setUser(user))
+                    .createBadgedIconBitmap(
+                            icon,
+                            new IconOptions().setUser(user).setIsCloneProfile(isClone))
                     .newIcon(context);
         }
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index 2614644..688fc72 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -55,6 +55,7 @@
         public ComponentName settingsComponentName;
         public CharSequence description;
         public Drawable previewImage;
+        public boolean supportsComplications = false;
 
         @Override
         public String toString() {
@@ -175,6 +176,7 @@
             if (dreamMetadata != null) {
                 dreamInfo.settingsComponentName = dreamMetadata.settingsActivity;
                 dreamInfo.previewImage = dreamMetadata.previewImage;
+                dreamInfo.supportsComplications = dreamMetadata.showComplications;
             }
             dreamInfos.add(dreamInfo);
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index 6a1cee3..562d20d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -224,6 +224,9 @@
                     mMetricsLogger.logOnConditionSelected();
                     updateAlarmWarningText(tag.condition);
                 }
+                tag.line1.setStateDescription(
+                        isChecked ? buttonView.getContext().getString(
+                                com.android.internal.R.string.selected) : null);
             }
         });
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
index 87e97b1..abbdaa7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenDurationDialog.java
@@ -196,6 +196,9 @@
                 if (isChecked) {
                     tag.rb.setChecked(true);
                 }
+                tag.line1.setStateDescription(
+                        isChecked ? buttonView.getContext().getString(
+                                com.android.internal.R.string.selected) : null);
             }
         });
 
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
index 59d5674..6b81c1a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/EnableZenModeDialogTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib.notification;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -78,6 +80,8 @@
         mController.mForeverId =  Condition.newId(mContext).appendPath("forever").build();
         when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
                 .thenReturn("testSummary");
+        when(mContext.getString(com.android.internal.R.string.selected))
+                .thenReturn("selected");
         NotificationManager.Policy alarmsEnabledPolicy = new NotificationManager.Policy(
                 NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 0, 0, 0);
         doReturn(alarmsEnabledPolicy).when(mNotificationManager).getNotificationPolicy();
@@ -190,4 +194,25 @@
         // alarm warning should NOT be null
         assertNotNull(mController.computeAlarmWarningText(null));
     }
+
+    @Test
+    public void testAccessibility() {
+        mController.bindConditions(null);
+        EnableZenModeDialog.ConditionTag forever = mController.getConditionTagAt(
+                ZenDurationDialog.FOREVER_CONDITION_INDEX);
+        EnableZenModeDialog.ConditionTag countdown = mController.getConditionTagAt(
+                ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+        EnableZenModeDialog.ConditionTag alwaysAsk = mController.getConditionTagAt(
+                ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX);
+
+        forever.rb.setChecked(true);
+        assertThat(forever.line1.getStateDescription().toString()).isEqualTo("selected");
+        assertThat(countdown.line1.getStateDescription()).isNull();
+        assertThat(alwaysAsk.line1.getStateDescription()).isNull();
+
+        alwaysAsk.rb.setChecked(true);
+        assertThat(forever.line1.getStateDescription()).isNull();
+        assertThat(countdown.line1.getStateDescription()).isNull();
+        assertThat(alwaysAsk.line1.getStateDescription().toString()).isEqualTo("selected");
+    }
 }
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
index 437c0d4..fc45e89 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/ZenDurationDialogTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib.notification;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
@@ -205,4 +207,27 @@
                 ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
         assertEquals(120, tag.countdownZenDuration);
     }
+
+    @Test
+    public void testAccessibility() {
+        Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_DURATION,
+                Settings.Secure.ZEN_DURATION_FOREVER);
+        mController.setupDialog(mBuilder);
+        ZenDurationDialog.ConditionTag forever = mController.getConditionTagAt(
+                ZenDurationDialog.FOREVER_CONDITION_INDEX);
+        ZenDurationDialog.ConditionTag countdown = mController.getConditionTagAt(
+                ZenDurationDialog.COUNTDOWN_CONDITION_INDEX);
+        ZenDurationDialog.ConditionTag alwaysAsk = mController.getConditionTagAt(
+                ZenDurationDialog.ALWAYS_ASK_CONDITION_INDEX);
+
+        forever.rb.setChecked(true);
+        assertThat(forever.line1.getStateDescription().toString()).isEqualTo("selected");
+        assertThat(countdown.line1.getStateDescription()).isNull();
+        assertThat(alwaysAsk.line1.getStateDescription()).isNull();
+
+        alwaysAsk.rb.setChecked(true);
+        assertThat(forever.line1.getStateDescription()).isNull();
+        assertThat(countdown.line1.getStateDescription()).isNull();
+        assertThat(alwaysAsk.line1.getStateDescription().toString()).isEqualTo("selected");
+    }
 }
\ No newline at end of file
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 210a387..93394f3 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -142,6 +142,8 @@
         Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION,
         Settings.Secure.VOLUME_HUSH_GESTURE,
         Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT,
+        Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
+        Settings.Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED,
         Settings.Secure.HUSH_GESTURE_USED,
         Settings.Secure.IN_CALL_NOTIFICATION_ENABLED,
         Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 39cd24a..9657862 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -219,6 +219,8 @@
                 COLON_SEPARATED_PACKAGE_LIST_VALIDATOR); // legacy restore setting
         VALIDATORS.put(Secure.HUSH_GESTURE_USED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.MANUAL_RINGER_TOGGLE_COUNT, NON_NEGATIVE_INTEGER_VALIDATOR);
+        VALIDATORS.put(Secure.LOW_POWER_WARNING_ACKNOWLEDGED, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Secure.EXTRA_LOW_POWER_WARNING_ACKNOWLEDGED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.IN_CALL_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 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 574fd5a..11154d1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -182,6 +182,8 @@
             "visible_pattern_enabled";
     private static final String KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS =
             "power_button_instantly_locks";
+    private static final String KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY =
+            "pin_enhanced_privacy";
 
     // Name of the temporary file we use during full backup/restore.  This is
     // stored in the full-backup tarfile as well, so should not be changed.
@@ -709,6 +711,10 @@
                 out.writeUTF(KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS);
                 out.writeUTF(powerButtonInstantlyLocks ? "1" : "0");
             }
+            if (lockPatternUtils.isPinEnhancedPrivacyEverChosen(userId)) {
+                out.writeUTF(KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY);
+                out.writeUTF(lockPatternUtils.isPinEnhancedPrivacyEnabled(userId) ? "1" : "0");
+            }
             // End marker
             out.writeUTF("");
             out.flush();
@@ -961,6 +967,9 @@
                     case KEY_LOCK_SETTINGS_POWER_BUTTON_INSTANTLY_LOCKS:
                         lockPatternUtils.setPowerButtonInstantlyLocks("1".equals(value), userId);
                         break;
+                    case KEY_LOCK_SETTINGS_PIN_ENHANCED_PRIVACY:
+                        lockPatternUtils.setPinEnhancedPrivacyEnabled("1".equals(value), userId);
+                        break;
                 }
             }
             in.close();
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index c0176d5..278ceb9 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -322,6 +322,7 @@
                     Settings.Global.LOW_BATTERY_SOUND,
                     Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
                     Settings.Global.LOW_POWER_MODE,
+                    Settings.Global.EXTRA_LOW_POWER_MODE,
                     Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
                     Settings.Global.LOW_POWER_MODE_STICKY,
                     Settings.Global.LOW_POWER_MODE_SUGGESTION_PARAMS,
@@ -800,7 +801,6 @@
                  Settings.Secure.PARENTAL_CONTROL_REDIRECT_URL,
                  Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
                  Settings.Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT,
-                 Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
                  Settings.Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION,
                  Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE,
                  Settings.Secure.FLASHLIGHT_AVAILABLE,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 596ff0e..90bec42 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -646,7 +646,7 @@
     <!-- Permission required for CTS test - ResourceObserverNativeTest -->
     <uses-permission android:name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
 
-    <!-- Permission required for CTS test - CtsPermission5TestCases -->
+    <!-- Permission required for CTS test - CtsAttributionSourceTestCases -->
     <uses-permission android:name="android.permission.RENOUNCE_PERMISSIONS" />
 
     <!-- Permission required for CTS test - android.widget.cts.ToastTest -->
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 9d46961..b236ac5 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -449,6 +449,7 @@
                 enabled: true,
                 optimize: true,
                 shrink: true,
+                shrink_resources: true,
                 proguard_compatibility: false,
                 proguard_flags_files: ["proguard.flags"],
             },
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
index 40a5e97..c49a487 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Expandable.kt
@@ -26,7 +26,7 @@
      * currently not attached or visible).
      *
      * @param cujType the CUJ type from the [com.android.internal.jank.InteractionJankMonitor]
-     * associated to the launch that will use this controller.
+     *   associated to the launch that will use this controller.
      */
     fun activityLaunchController(cujType: Int? = null): ActivityLaunchAnimator.Controller?
 
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
index 9668066..3417ffd 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchAnimator.kt
@@ -75,7 +75,7 @@
          * - Get the associated [Context].
          * - Compute whether we are expanding fully above the launch container.
          * - Get to overlay to which we initially put the window background layer, until the opening
-         * window is made visible (see [openingWindowSyncView]).
+         *   window is made visible (see [openingWindowSyncView]).
          *
          * This container can be changed to force this [Controller] to animate the expanding view
          * inside a different location, for instance to ensure correct layering during the
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
index b98b9221..ed8e705 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -24,7 +24,7 @@
      * Set whether this view should block/postpone all calls to [View.setVisibility]. This ensures
      * that this view:
      * - remains invisible during the launch animation given that it is ghosted and already drawn
-     * somewhere else.
+     *   somewhere else.
      * - remains invisible as long as a dialog expanded from it is shown.
      * - restores its expected visibility once the dialog expanded from it is dismissed.
      *
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
index 0e2d23b..6946e6b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt
@@ -182,9 +182,9 @@
          * Represents a TransitionInfo object as an array of old-style targets
          *
          * @param wallpapers If true, this will return wallpaper targets; otherwise it returns
-         * non-wallpaper targets.
+         *   non-wallpaper targets.
          * @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should
-         * be populated by this function. If null, it is ignored.
+         *   be populated by this function. If null, it is ignored.
          */
         fun wrapTargets(
             info: TransitionInfo,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
index a96f893..b89a8b0 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ShadeInterpolation.kt
@@ -6,6 +6,7 @@
 
     /**
      * Interpolate alpha for notification background scrim during shade expansion.
+     *
      * @param fraction Shade expansion fraction
      */
     @JvmStatic
@@ -16,6 +17,7 @@
 
     /**
      * Interpolate alpha for shade content during shade expansion.
+     *
      * @param fraction Shade expansion fraction
      */
     @JvmStatic
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
index 341784e..468a8b1 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
@@ -161,7 +161,6 @@
      * This API is useful to continue animation from the middle of the state. For example, if you
      * animate weight from 200 to 400, then if you want to move back to 200 at the half of the
      * animation, it will look like
-     *
      * <pre> <code>
      * ```
      *     val interp = TextInterpolator(layout)
@@ -497,7 +496,9 @@
                 count,
                 layout.textDirectionHeuristic,
                 paint
-            ) { _, _, glyphs, _ -> runs.add(glyphs) }
+            ) { _, _, glyphs, _ ->
+                runs.add(glyphs)
+            }
             out.add(runs)
 
             if (lineNo > 0) {
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 052888b..b5b6037 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
@@ -25,7 +25,6 @@
 
 /**
  * Shader class that renders an expanding ripple effect. The ripple contains three elements:
- *
  * 1. an expanding filled [RippleShape] that appears in the beginning and quickly fades away
  * 2. an expanding ring that appears throughout the effect
  * 3. an expanding ring-shaped area that reveals noise over #2.
@@ -317,6 +316,7 @@
      * Parameters used for fade in and outs of the ripple.
      *
      * <p>Note that all the fade in/ outs are "linear" progression.
+     *
      * ```
      *          (opacity)
      *          1
@@ -331,6 +331,7 @@
      *               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.
      */
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
index 79bc2f4..89871fa7 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
@@ -30,12 +30,14 @@
      * Noise move speed variables.
      *
      * Its sign determines the direction; magnitude determines the speed. <ul>
+     *
      * ```
      *     <li> [noiseMoveSpeedX] positive: right to left; negative: left to right.
      *     <li> [noiseMoveSpeedY] positive: bottom to top; negative: top to bottom.
      *     <li> [noiseMoveSpeedZ] its sign doesn't matter much, as it moves in Z direction. Use it
      *     to add turbulence in place.
      * ```
+     *
      * </ul>
      */
     val noiseMoveSpeedX: Float = 0f,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt b/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt
new file mode 100644
index 0000000..35dbb89
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/util/AnimatorExtensions.kt
@@ -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.systemui.util
+
+import androidx.core.animation.Animator
+
+/**
+ * Add an action which will be invoked when the animation has ended.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.end
+ */
+inline fun Animator.doOnEnd(
+    crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onEnd = action)
+
+/**
+ * Add an action which will be invoked when the animation has started.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.start
+ */
+inline fun Animator.doOnStart(
+    crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onStart = action)
+
+/**
+ * Add an action which will be invoked when the animation has been cancelled.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ * @see Animator.cancel
+ */
+inline fun Animator.doOnCancel(
+    crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onCancel = action)
+
+/**
+ * Add an action which will be invoked when the animation has repeated.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ */
+inline fun Animator.doOnRepeat(
+    crossinline action: (animator: Animator) -> Unit
+): Animator.AnimatorListener = addListener(onRepeat = action)
+
+/**
+ * Add a listener to this Animator using the provided actions.
+ *
+ * @return the [Animator.AnimatorListener] added to the Animator
+ */
+inline fun Animator.addListener(
+    crossinline onEnd: (animator: Animator) -> Unit = {},
+    crossinline onStart: (animator: Animator) -> Unit = {},
+    crossinline onCancel: (animator: Animator) -> Unit = {},
+    crossinline onRepeat: (animator: Animator) -> Unit = {}
+): Animator.AnimatorListener {
+    val listener =
+        object : Animator.AnimatorListener {
+            override fun onAnimationRepeat(animator: Animator) = onRepeat(animator)
+            override fun onAnimationEnd(animator: Animator) = onEnd(animator)
+            override fun onAnimationCancel(animator: Animator) = onCancel(animator)
+            override fun onAnimationStart(animator: Animator) = onStart(animator)
+        }
+    addListener(listener)
+    return listener
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
new file mode 100644
index 0000000..30e2a25
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/DumpableNotRegisteredDetector.kt
@@ -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.internal.systemui.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Context
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Location
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiMethod
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UClass
+
+/**
+ * Checks if any class has implemented the `Dumpable` interface but has not registered itself with
+ * the `DumpManager`.
+ */
+@Suppress("UnstableApiUsage")
+class DumpableNotRegisteredDetector : Detector(), SourceCodeScanner {
+
+    private var isDumpable: Boolean = false
+    private var isCoreStartable: Boolean = false
+    private var hasRegisterCall: Boolean = false
+    private var classLocation: Location? = null
+
+    override fun beforeCheckFile(context: Context) {
+        isDumpable = false
+        isCoreStartable = false
+        hasRegisterCall = false
+        classLocation = null
+    }
+
+    override fun applicableSuperClasses(): List<String> {
+        return listOf(DUMPABLE_CLASS_NAME)
+    }
+
+    override fun getApplicableMethodNames(): List<String> {
+        return listOf("registerDumpable", "registerNormalDumpable", "registerCriticalDumpable")
+    }
+
+    override fun visitClass(context: JavaContext, declaration: UClass) {
+        if (declaration.isInterface || context.evaluator.isAbstract(declaration)) {
+            // Don't require interfaces or abstract classes to call `register` (assume the full
+            // implementations will call it). This also means that we correctly don't warn for the
+            // `Dumpable` interface itself.
+            return
+        }
+
+        classLocation = context.getNameLocation(declaration)
+
+        val superTypeClassNames = declaration.superTypes.mapNotNull { it.resolve()?.qualifiedName }
+        isDumpable = superTypeClassNames.contains(DUMPABLE_CLASS_NAME)
+        isCoreStartable = superTypeClassNames.contains(CORE_STARTABLE_CLASS_NAME)
+    }
+
+    override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+        if (context.evaluator.isMemberInSubClassOf(method, DUMP_MANAGER_CLASS_NAME)) {
+            hasRegisterCall = true
+        }
+    }
+
+    override fun afterCheckFile(context: Context) {
+        if (!isDumpable) {
+            return
+        }
+        if (isDumpable && isCoreStartable) {
+            // CoreStartables will be automatically registered, so classes that implement
+            // CoreStartable do not need a `register` call.
+            return
+        }
+
+        if (!hasRegisterCall) {
+            context.report(
+                issue = ISSUE,
+                location = classLocation!!,
+                message =
+                    "Any class implementing `Dumpable` must call " +
+                        "`DumpManager.registerNormalDumpable` or " +
+                        "`DumpManager.registerCriticalDumpable`",
+            )
+        }
+    }
+
+    companion object {
+        @JvmField
+        val ISSUE: Issue =
+            Issue.create(
+                id = "DumpableNotRegistered",
+                briefDescription = "Dumpable not registered with DumpManager.",
+                explanation =
+                    """
+                    This class has implemented the `Dumpable` interface, but it has not registered \
+                    itself with the `DumpManager`. This means that the class will never actually \
+                    be dumped. Please call `DumpManager.registerNormalDumpable` or \
+                    `DumpManager.registerCriticalDumpable` in the class's constructor or \
+                    initialization method.""",
+                category = Category.CORRECTNESS,
+                priority = 8,
+                severity = Severity.WARNING,
+                implementation =
+                    Implementation(DumpableNotRegisteredDetector::class.java, Scope.JAVA_FILE_SCOPE)
+            )
+
+        private const val DUMPABLE_CLASS_NAME = "com.android.systemui.Dumpable"
+        private const val CORE_STARTABLE_CLASS_NAME = "com.android.systemui.CoreStartable"
+        private const val DUMP_MANAGER_CLASS_NAME = "com.android.systemui.dump.DumpManager"
+    }
+}
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index 254a6fb..84f7050 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -32,6 +32,7 @@
                 BindServiceOnMainThreadDetector.ISSUE,
                 BroadcastSentViaContextDetector.ISSUE,
                 CleanArchitectureDependencyViolationDetector.ISSUE,
+                DumpableNotRegisteredDetector.ISSUE,
                 SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY,
                 SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY,
                 NonInjectedMainThreadDetector.ISSUE,
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
index a4b59fd..a5f832a 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/CleanArchitectureDependencyViolationDetectorTest.kt
@@ -64,7 +64,8 @@
                         class BadClass(
                             private val viewModel: ViewModel,
                         )
-                    """.trimIndent()
+                    """
+                        .trimIndent()
                 )
             )
             .issues(
@@ -98,7 +99,8 @@
                         class BadClass(
                             private val repository: Repository,
                         )
-                    """.trimIndent()
+                    """
+                        .trimIndent()
                 )
             )
             .issues(
@@ -136,7 +138,8 @@
                             private val interactor: Interactor,
                             private val viewmodel: ViewModel,
                         )
-                    """.trimIndent()
+                    """
+                        .trimIndent()
                 )
             )
             .issues(
@@ -176,7 +179,8 @@
                         class BadClass(
                             private val interactor: Interactor,
                         )
-                    """.trimIndent()
+                    """
+                        .trimIndent()
                 )
             )
             .issues(
@@ -207,7 +211,8 @@
                     data class Model(
                         private val name: String,
                     )
-                """.trimIndent()
+                """
+                    .trimIndent()
             )
         private val REPOSITORY_FILE =
             TestFiles.kotlin(
@@ -228,7 +233,8 @@
                             return models
                         }
                     }
-                """.trimIndent()
+                """
+                    .trimIndent()
             )
         private val INTERACTOR_FILE =
             TestFiles.kotlin(
@@ -245,7 +251,8 @@
                             return repository.getModels()
                         }
                     }
-                """.trimIndent()
+                """
+                    .trimIndent()
             )
         private val VIEW_MODEL_FILE =
             TestFiles.kotlin(
@@ -262,7 +269,8 @@
                             return interactor.getModels().map { model -> model.name }
                         }
                     }
-                """.trimIndent()
+                """
+                    .trimIndent()
             )
         private val NON_CLEAN_ARCHITECTURE_FILE =
             TestFiles.kotlin(
@@ -282,7 +290,8 @@
                             )
                         }
                     }
-                """.trimIndent()
+                """
+                    .trimIndent()
             )
         private val LEGITIMATE_FILES =
             arrayOf(
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
new file mode 100644
index 0000000..3d6cbc7
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/DumpableNotRegisteredDetectorTest.kt
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+@Suppress("UnstableApiUsage")
+class DumpableNotRegisteredDetectorTest : SystemUILintDetectorTest() {
+    override fun getDetector(): Detector = DumpableNotRegisteredDetector()
+
+    override fun getIssues(): List<Issue> = listOf(DumpableNotRegisteredDetector.ISSUE)
+
+    @Test
+    fun classIsNotDumpable_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                    """
+                    package test.pkg;
+
+                    class SomeClass() {
+                    }
+                """.trimIndent()
+                ),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classIsDumpable_andRegisterIsCalled_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                    """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+                    import com.android.systemui.dump.DumpManager;
+
+                    public class SomeClass implements Dumpable {
+                        SomeClass(DumpManager dumpManager) {
+                            dumpManager.registerDumpable(this);
+                        }
+
+                        @Override
+                        void dump(PrintWriter pw, String[] args) {
+                            pw.println("testDump");
+                        }
+                    }
+                """.trimIndent()
+                ),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classIsDumpable_andRegisterNormalIsCalled_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                    """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+                    import com.android.systemui.dump.DumpManager;
+
+                    public class SomeClass implements Dumpable {
+                        SomeClass(DumpManager dumpManager) {
+                            dumpManager.registerNormalDumpable(this);
+                        }
+
+                        @Override
+                        void dump(PrintWriter pw, String[] args) {
+                            pw.println("testDump");
+                        }
+                    }
+                """.trimIndent()
+                ),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classIsDumpable_andRegisterCriticalIsCalled_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                    """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+                    import com.android.systemui.dump.DumpManager;
+
+                    public class SomeClass implements Dumpable {
+                        SomeClass(DumpManager dumpManager) {
+                            dumpManager.registerCriticalDumpable(this);
+                        }
+
+                        @Override
+                        void dump(PrintWriter pw, String[] args) {
+                            pw.println("testDump");
+                        }
+                    }
+                """.trimIndent()
+                ),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classIsDumpable_noRegister_violation() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+
+                    public class SomeClass implements Dumpable {
+                        @Override
+                        public void dump() {
+                        }
+                    }
+                """
+                    )
+                    .indented(),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expect(
+                ("""
+                src/test/pkg/SomeClass.java:5: Warning: Any class implementing Dumpable must call DumpManager.registerNormalDumpable or DumpManager.registerCriticalDumpable [DumpableNotRegistered]
+                public class SomeClass implements Dumpable {
+                             ~~~~~~~~~
+                0 errors, 1 warnings
+                """)
+                    .trimIndent()
+            )
+    }
+
+    @Test
+    fun classIsDumpable_usesNotDumpManagerMethod_violation() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+                    import com.android.systemui.OtherRegistrationObject;
+
+                    public class SomeClass implements Dumpable {
+                        public SomeClass(OtherRegistrationObject otherRegistrationObject) {
+                            otherRegistrationObject.registerDumpable(this);
+                        }
+                        @Override
+                        public void dump() {
+                        }
+                    }
+                """
+                    )
+                    .indented(),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expect(
+                ("""
+                src/test/pkg/SomeClass.java:6: Warning: Any class implementing Dumpable must call DumpManager.registerNormalDumpable or DumpManager.registerCriticalDumpable [DumpableNotRegistered]
+                public class SomeClass implements Dumpable {
+                             ~~~~~~~~~
+                0 errors, 1 warnings
+                """)
+                    .trimIndent()
+            )
+    }
+
+    @Test
+    fun classIsDumpableAndCoreStartable_noRegister_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+                    import com.android.systemui.CoreStartable;
+
+                    public class SomeClass implements Dumpable, CoreStartable {
+                        @Override
+                        public void start() {
+                        }
+
+                        @Override
+                        public void dump() {
+                        }
+                    }
+                """
+                    )
+                    .indented(),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun classIsAbstract_noRegister_noViolation() {
+        lint()
+            .files(
+                TestFiles.java(
+                        """
+                    package test.pkg;
+
+                    import com.android.systemui.Dumpable;
+
+                    public abstract class SomeClass implements Dumpable {
+                        void abstractMethodHere();
+
+                        @Override
+                        public void dump() {
+                        }
+                    }
+                """
+                    )
+                    .indented(),
+                *stubs,
+            )
+            .issues(DumpableNotRegisteredDetector.ISSUE)
+            .run()
+            .expectClean()
+    }
+
+    companion object {
+        private val DUMPABLE_STUB =
+            TestFiles.java(
+                    """
+                    package com.android.systemui;
+
+                    import com.android.systemui.dump.DumpManager;
+                    import java.io.PrintWriter;
+
+                    public interface Dumpable {
+                        void dump();
+                    }
+                """
+                )
+                .indented()
+
+        private val DUMP_MANAGER_STUB =
+            TestFiles.java(
+                    """
+                    package com.android.systemui.dump;
+
+                    public interface DumpManager {
+                        void registerDumpable(Dumpable module);
+                        void registerNormalDumpable(Dumpable module);
+                        void registerCriticalDumpable(Dumpable module);
+                    }
+                """
+                )
+                .indented()
+
+        private val OTHER_REGISTRATION_OBJECT_STUB =
+            TestFiles.java(
+                    """
+                    package com.android.systemui;
+
+                    public interface OtherRegistrationObject {
+                        void registerDumpable(Dumpable module);
+                    }
+                """
+                )
+                .indented()
+
+        private val CORE_STARTABLE_STUB =
+            TestFiles.java(
+                    """
+                    package com.android.systemui;
+
+                    public interface CoreStartable {
+                        void start();
+                    }
+                """
+                )
+                .indented()
+
+        private val stubs =
+            arrayOf(
+                DUMPABLE_STUB,
+                DUMP_MANAGER_STUB,
+                OTHER_REGISTRATION_OBJECT_STUB,
+                CORE_STARTABLE_STUB,
+            )
+    }
+}
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt b/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
index a02954a..08ab146 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/SystemUiController.kt
@@ -78,11 +78,10 @@
      * Set the status bar color.
      *
      * @param color The **desired** [Color] to set. This may require modification if running on an
-     * API level that only supports white status bar icons.
+     *   API level that only supports white status bar icons.
      * @param darkIcons Whether dark status bar icons would be preferable.
      * @param transformColorForLightContent A lambda which will be invoked to transform [color] if
-     * dark icons were requested but are not available. Defaults to applying a black scrim.
-     *
+     *   dark icons were requested but are not available. Defaults to applying a black scrim.
      * @see statusBarDarkContentEnabled
      */
     fun setStatusBarColor(
@@ -95,16 +94,15 @@
      * Set the navigation bar color.
      *
      * @param color The **desired** [Color] to set. This may require modification if running on an
-     * API level that only supports white navigation bar icons. Additionally this will be ignored
-     * and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or the
-     * system UI automatically applies background protection in other navigation modes.
+     *   API level that only supports white navigation bar icons. Additionally this will be ignored
+     *   and [Color.Transparent] will be used on API 29+ where gesture navigation is preferred or
+     *   the system UI automatically applies background protection in other navigation modes.
      * @param darkIcons Whether dark navigation bar icons would be preferable.
      * @param navigationBarContrastEnforced Whether the system should ensure that the navigation bar
-     * has enough contrast when a fully transparent background is requested. Only supported on API
-     * 29+.
+     *   has enough contrast when a fully transparent background is requested. Only supported on API
+     *   29+.
      * @param transformColorForLightContent A lambda which will be invoked to transform [color] if
-     * dark icons were requested but are not available. Defaults to applying a black scrim.
-     *
+     *   dark icons were requested but are not available. Defaults to applying a black scrim.
      * @see navigationBarDarkContentEnabled
      * @see navigationBarContrastEnforced
      */
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
index cfc38df..d4a81f9 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/Expandable.kt
@@ -255,7 +255,9 @@
                     .onGloballyPositioned {
                         controller.boundsInComposeViewRoot.value = it.boundsInRoot()
                     }
-            ) { wrappedContent(controller.expandable) }
+            ) {
+                wrappedContent(controller.expandable)
+            }
         }
         else -> {
             val clickModifier =
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
index edb10c7d..767756e 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/animation/ExpandableController.kt
@@ -156,9 +156,9 @@
      * Create a [LaunchAnimator.Controller] that is going to be used to drive an activity or dialog
      * animation. This controller will:
      * 1. Compute the start/end animation state using [boundsInComposeViewRoot] and the location of
-     * composeViewRoot on the screen.
+     *    composeViewRoot on the screen.
      * 2. Update [animatorState] with the current animation state if we are animating, or null
-     * otherwise.
+     *    otherwise.
      */
     private fun launchController(): LaunchAnimator.Controller {
         return object : LaunchAnimator.Controller {
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
index eb9d625..a80a1f9 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/Pager.kt
@@ -86,21 +86,20 @@
 /**
  * A horizontally scrolling layout that allows users to flip between items to the left and right.
  *
- * @sample com.google.accompanist.sample.pager.HorizontalPagerSample
- *
  * @param count the number of pages.
  * @param modifier the modifier to apply to this layout.
  * @param state the state object to be used to control or observe the pager's state.
  * @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the end to the start and [PagerState.currentPage] == 0 will mean the first item is
- * located at the end.
+ *   composed from the end to the start and [PagerState.currentPage] == 0 will mean the first item
+ *   is located at the end.
  * @param itemSpacing horizontal spacing to add between items.
  * @param flingBehavior logic describing fling behavior.
  * @param key the scroll position will be maintained based on the key, which means if you add/remove
- * items before the current visible item the item with the given key will be kept as the first
- * visible one.
+ *   items before the current visible item the item with the given key will be kept as the first
+ *   visible one.
  * @param content a block which describes the content. Inside this block you can reference
- * [PagerScope.currentPage] and other properties in [PagerScope].
+ *   [PagerScope.currentPage] and other properties in [PagerScope].
+ * @sample com.google.accompanist.sample.pager.HorizontalPagerSample
  */
 @ExperimentalPagerApi
 @Composable
@@ -134,21 +133,20 @@
 /**
  * A vertically scrolling layout that allows users to flip between items to the top and bottom.
  *
- * @sample com.google.accompanist.sample.pager.VerticalPagerSample
- *
  * @param count the number of pages.
  * @param modifier the modifier to apply to this layout.
  * @param state the state object to be used to control or observe the pager's state.
  * @param reverseLayout reverse the direction of scrolling and layout, when `true` items will be
- * composed from the bottom to the top and [PagerState.currentPage] == 0 will mean the first item is
- * located at the bottom.
+ *   composed from the bottom to the top and [PagerState.currentPage] == 0 will mean the first item
+ *   is located at the bottom.
  * @param itemSpacing vertical spacing to add between items.
  * @param flingBehavior logic describing fling behavior.
  * @param key the scroll position will be maintained based on the key, which means if you add/remove
- * items before the current visible item the item with the given key will be kept as the first
- * visible one.
+ *   items before the current visible item the item with the given key will be kept as the first
+ *   visible one.
  * @param content a block which describes the content. Inside this block you can reference
- * [PagerScope.currentPage] and other properties in [PagerScope].
+ *   [PagerScope.currentPage] and other properties in [PagerScope].
+ * @sample com.google.accompanist.sample.pager.VerticalPagerSample
  */
 @ExperimentalPagerApi
 @Composable
@@ -246,7 +244,9 @@
                         // Constraint the content to be <= than the size of the pager.
                         .fillParentMaxHeight()
                         .wrapContentSize()
-                ) { pagerScope.content(page) }
+                ) {
+                    pagerScope.content(page)
+                }
             }
         }
     } else {
@@ -272,7 +272,9 @@
                         // Constraint the content to be <= than the size of the pager.
                         .fillParentMaxWidth()
                         .wrapContentSize()
-                ) { pagerScope.content(page) }
+                ) {
+                    pagerScope.content(page)
+                }
             }
         }
     }
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
index 2e6ae78..1822a68 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/PagerState.kt
@@ -198,7 +198,7 @@
      *
      * @param page the page to animate to. Must be between 0 and [pageCount] (inclusive).
      * @param pageOffset the percentage of the page width to offset, from the start of [page]. Must
-     * be in the range 0f..1f.
+     *   be in the range 0f..1f.
      */
     suspend fun animateScrollToPage(
         @IntRange(from = 0) page: Int,
diff --git a/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt b/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
index 23122de..9814029 100644
--- a/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
+++ b/packages/SystemUI/compose/core/src/com/android/compose/pager/SnappingFlingBehavior.kt
@@ -44,11 +44,11 @@
 /**
  * Create and remember a snapping [FlingBehavior] to be used with [LazyListState].
  *
- * TODO: move this to a new module and make it public
- *
  * @param lazyListState The [LazyListState] to update.
  * @param decayAnimationSpec The decay animation spec to use for decayed flings.
  * @param snapAnimationSpec The animation spec to use when snapping.
+ *
+ * TODO: move this to a new module and make it public
  */
 @Composable
 internal fun rememberSnappingFlingBehavior(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
index 3eeadae..a74e56b 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreen.kt
@@ -60,7 +60,7 @@
  *
  * @param viewModel the [PeopleViewModel] that should be composed.
  * @param onResult the callback called with the result of this screen. Callers should usually finish
- * the Activity/Fragment/View hosting this Composable once a result is available.
+ *   the Activity/Fragment/View hosting this Composable once a result is available.
  */
 @Composable
 fun PeopleScreen(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
index 3f590df..0484ff4 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/people/ui/compose/PeopleScreenEmpty.kt
@@ -79,7 +79,9 @@
                     containerColor = androidColors.colorAccentPrimary,
                     contentColor = androidColors.textColorOnAccent,
                 )
-        ) { Text(stringResource(R.string.got_it)) }
+        ) {
+            Text(stringResource(R.string.got_it))
+        }
     }
 }
 
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 ab36d58..00c0a0b 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
@@ -38,6 +38,7 @@
 
 private val TAG = ClockRegistry::class.simpleName!!
 private const val DEBUG = true
+private val KEY_TIMESTAMP = "appliedTimestamp"
 
 /** ClockRegistry aggregates providers and plugins */
 open class ClockRegistry(
@@ -134,9 +135,9 @@
         assertNotMainThread()
 
         try {
-            value?._applied_timestamp = System.currentTimeMillis()
-            val json = ClockSettings.serialize(value)
+            value?.metadata?.put(KEY_TIMESTAMP, System.currentTimeMillis())
 
+            val json = ClockSettings.serialize(value)
             if (handleAllUsers) {
                 Settings.Secure.putStringForUser(
                     context.contentResolver,
@@ -172,7 +173,7 @@
         clockChangeListeners.forEach(func)
     }
 
-    private fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
+    public fun mutateSetting(mutator: (ClockSettings) -> ClockSettings) {
         scope.launch(bgDispatcher) { applySettings(mutator(settings ?: ClockSettings())) }
     }
 
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 2a40f5c..4df7a44 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
@@ -95,7 +95,7 @@
 
     open inner class DefaultClockFaceController(
         override val view: AnimatableClockView,
-        val seedColor: Int?,
+        var seedColor: Int?,
     ) : ClockFaceController {
 
         // MAGENTA is a placeholder, and will be assigned correctly in initialize
@@ -111,9 +111,9 @@
 
         init {
             if (seedColor != null) {
-                currentColor = seedColor
+                currentColor = seedColor!!
             }
-            view.setColors(currentColor, currentColor)
+            view.setColors(DOZE_COLOR, currentColor)
         }
 
         override val events =
@@ -141,7 +141,7 @@
         fun updateColor() {
             val color =
                 if (seedColor != null) {
-                    seedColor
+                    seedColor!!
                 } else if (isRegionDark) {
                     resources.getColor(android.R.color.system_accent1_100)
                 } else {
@@ -194,6 +194,14 @@
             smallClock.updateColor()
         }
 
+        override fun onSeedColorChanged(seedColor: Int?) {
+            largeClock.seedColor = seedColor
+            smallClock.seedColor = seedColor
+
+            largeClock.updateColor()
+            smallClock.updateColor()
+        }
+
         override fun onLocaleChanged(locale: Locale) {
             val nf = NumberFormat.getInstance(locale)
             if (nf.format(FORMAT_NUMBER.toLong()) == burmeseNumerals) {
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 c120876..0d88075 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
@@ -51,7 +51,7 @@
          *
          * Supported operations:
          * - Query - to know which slots are available, query the [SlotTable.URI] [Uri]. The result
-         * set will contain rows with the [SlotTable.Columns] columns.
+         *   set will contain rows with the [SlotTable.Columns] columns.
          */
         object SlotTable {
             const val TABLE_NAME = "slots"
@@ -74,8 +74,8 @@
          *
          * Supported operations:
          * - Query - to know about all the affordances that are available on the device, regardless
-         * of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
-         * set will contain rows, each with the columns specified in [AffordanceTable.Columns].
+         *   of which ones are currently selected, query the [AffordanceTable.URI] [Uri]. The result
+         *   set will contain rows, each with the columns specified in [AffordanceTable.Columns].
          */
         object AffordanceTable {
             const val TABLE_NAME = "affordances"
@@ -128,14 +128,14 @@
          *
          * Supported operations:
          * - Insert - to insert an affordance and place it in a slot, insert values for the columns
-         * into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the system.
-         * Selecting a new affordance for a slot that is already full will automatically remove the
-         * oldest affordance from the slot.
+         *   into the [SelectionTable.URI] [Uri]. The maximum capacity rule is enforced by the
+         *   system. Selecting a new affordance for a slot that is already full will automatically
+         *   remove the oldest affordance from the slot.
          * - Query - to know which affordances are set on which slots, query the
-         * [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
-         * columns from [SelectionTable.Columns].
+         *   [SelectionTable.URI] [Uri]. The result set will contain rows, each of which with the
+         *   columns from [SelectionTable.Columns].
          * - Delete - to unselect an affordance, removing it from a slot, delete from the
-         * [SelectionTable.URI] [Uri], passing in values for each column.
+         *   [SelectionTable.URI] [Uri], passing in values for each column.
          */
         object SelectionTable {
             const val TABLE_NAME = "selections"
@@ -160,7 +160,7 @@
      *
      * Supported operations:
      * - Query - to know the values of flags, query the [FlagsTable.URI] [Uri]. The result set will
-     * contain rows, each of which with the columns from [FlagsTable.Columns].
+     *   contain rows, each of which with the columns from [FlagsTable.Columns].
      */
     object FlagsTable {
         const val TABLE_NAME = "flags"
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
index ec860b5..18753fd 100644
--- a/packages/SystemUI/ktfmt_includes.txt
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -1,28 +1,20 @@
 +packages/SystemUI
 -packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
 -packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/BindServiceViaContextDetector.kt
 -packages/SystemUI/checks/src/com/android/internal/systemui/lint/BroadcastSentViaContextDetector.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/GetMainLooperViaContextDetector.kt
 -packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
 -packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt
--packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/BindServiceViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/BroadcastSentViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/GetMainLooperViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
--packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt
+-packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+-packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
 -packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
--packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt
+-packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/View.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/FlagListenable.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt
 -packages/SystemUI/shared/src/com/android/systemui/flags/FlagSettingsHelper.kt
 -packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt
 -packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
 -packages/SystemUI/shared/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerManager.kt
 -packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
@@ -35,8 +27,6 @@
 -packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
 -packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
 -packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
--packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
--packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
 -packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
 -packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherAnchor.kt
 -packages/SystemUI/src/com/android/keyguard/clock/ClockPalette.kt
@@ -65,12 +55,10 @@
 -packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
--packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
--packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpView.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
@@ -80,7 +68,6 @@
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyView.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmEmptyViewController.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt
--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
 -packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
@@ -93,8 +80,6 @@
 -packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
 -packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
 -packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
--packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
--packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
 -packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
 -packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
 -packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLogger.kt
@@ -102,7 +87,6 @@
 -packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
 -packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt
 -packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt
--packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
 -packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt
 -packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
 -packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -132,6 +116,7 @@
 -packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
 -packages/SystemUI/src/com/android/systemui/controls/management/ManagementPageIndicator.kt
 -packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/start/ControlsStartable.kt
 -packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
 -packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
 -packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
@@ -162,7 +147,6 @@
 -packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
 -packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
 -packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt
--packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
 -packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
 -packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
 -packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
@@ -172,20 +156,16 @@
 -packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
 -packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
 -packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+-packages/SystemUI/src/com/android/systemui/flags/Flags.kt
 -packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
 -packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
 -packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
--packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/LifecycleScreenStatusProvider.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfig.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartable.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
 -packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
--packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
--packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
--packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
--packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
--packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
 -packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt
--packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
 -packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
 -packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
 -packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
@@ -202,9 +182,15 @@
 -packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
 -packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
 -packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorResultHandler.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionRecentsViewController.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/RecentTasksAdapter.kt
+-packages/SystemUI/src/com/android/systemui/mediaprojection/devicepolicy/ScreenCaptureDevicePolicyResolver.kt
 -packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
 -packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
 -packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+-packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
 -packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
 -packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt
 -packages/SystemUI/src/com/android/systemui/privacy/MediaProjectionPrivacyItemMonitor.kt
@@ -220,8 +206,6 @@
 -packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
 -packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
 -packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
--packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
--packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
 -packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
 -packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
 -packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt
@@ -237,7 +221,6 @@
 -packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
 -packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialogEventLogger.kt
 -packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
--packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
 -packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
 -packages/SystemUI/src/com/android/systemui/qs/tileimpl/IgnorableChildLinearLayout.kt
 -packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -245,10 +228,6 @@
 -packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
 -packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
 -packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt
--packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
--packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt
 -packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
 -packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
 -packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
@@ -259,23 +238,21 @@
 -packages/SystemUI/src/com/android/systemui/settings/UserContentResolverProvider.kt
 -packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
 -packages/SystemUI/src/com/android/systemui/settings/UserFileManager.kt
--packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
 -packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
 -packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
 -packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
 -packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
 -packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
 -packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
--packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
 -packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
--packages/SystemUI/src/com/android/systemui/shade/NotifPanelEvents.kt
 -packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
 -packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
 -packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeHeightLogger.kt
 -packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
 -packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
 -packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
--packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
 -packages/SystemUI/src/com/android/systemui/smartspace/SmartspacePrecondition.kt
 -packages/SystemUI/src/com/android/systemui/smartspace/SmartspaceTargetFilter.kt
 -packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
@@ -284,9 +261,7 @@
 -packages/SystemUI/src/com/android/systemui/smartspace/preconditions/LockscreenPrecondition.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarWifiView.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
--packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt
@@ -311,10 +286,12 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/disableflags/DisableFlagsLogger.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusBarEventsModule.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerImpl.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureHandler.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
@@ -325,7 +302,6 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
@@ -403,6 +379,7 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
@@ -444,13 +421,10 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/ShadeStateListener.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
--packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/ConnectivitySlots.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
@@ -470,19 +444,17 @@
 -packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt
 -packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
--packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
 -packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt
+-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt
 -packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarRootView.kt
 -packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
 -packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
 -packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt
 -packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt
 -packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
--packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt
 -packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
 -packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt
--packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
--packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
 -packages/SystemUI/src/com/android/systemui/user/UserSwitcherPopupMenu.kt
 -packages/SystemUI/src/com/android/systemui/user/UserSwitcherRootView.kt
 -packages/SystemUI/src/com/android/systemui/util/AsyncActivityLauncher.kt
@@ -509,7 +481,6 @@
 -packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
 -packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
 -packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
--packages/SystemUI/src/com/android/systemui/util/collection/RingBuffer.kt
 -packages/SystemUI/src/com/android/systemui/util/concurrency/Execution.kt
 -packages/SystemUI/src/com/android/systemui/util/concurrency/PendingTasksContainer.kt
 -packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
@@ -517,6 +488,7 @@
 -packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
 -packages/SystemUI/src/com/android/systemui/util/kotlin/IpcSerializer.kt
 -packages/SystemUI/src/com/android/systemui/util/kotlin/nullability.kt
+-packages/SystemUI/src/com/android/systemui/util/recycler/HorizontalSpacerItemDecoration.kt
 -packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt
 -packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
 -packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
@@ -525,7 +497,6 @@
 -packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
 -packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
 -packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
--packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
 -packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
 -packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
 -packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
@@ -549,8 +520,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
--packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
@@ -569,7 +538,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
@@ -579,7 +547,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoritesModelTest.kt
--packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
@@ -596,13 +563,17 @@
 -packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceConfigTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/MuteQuickAffordanceCoreStartableTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepositoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/lifecycle/InstantTaskExecutorRule.kt
--packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyChipBuilderTest.kt
@@ -610,7 +581,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/QSContainerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
@@ -641,35 +611,28 @@
 -packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageCaptureImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
--packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
--packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/DragDownHelperTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -683,6 +646,7 @@
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/DisableStateTrackerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
@@ -719,7 +683,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
@@ -733,8 +696,7 @@
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/ShadeExpansionStateManagerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
@@ -744,7 +706,6 @@
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerOldImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
@@ -753,40 +714,34 @@
 -packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
--packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
--packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
 -packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
--packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/FakeSharedPreferencesTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/FloatingContentCoordinatorTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt
--packages/SystemUI/tests/src/com/android/systemui/util/collection/RingBufferTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/drawable/DrawableSizeTest.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/kotlin/IpcSerializerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/SuspendUtilTests.kt
 -packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt
--packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
 -packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt
 -packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSharedPreferences.kt
 -packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionProgressProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
 -packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
--packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
index 314c736..db88b59 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -171,7 +171,7 @@
             a1 = TonalSpec(HueSource(), ChromaConstant(36.0)),
             a2 = TonalSpec(HueSource(), ChromaConstant(16.0)),
             a3 = TonalSpec(HueAdd(60.0), ChromaConstant(24.0)),
-            n1 = TonalSpec(HueSource(), ChromaConstant(4.0)),
+            n1 = TonalSpec(HueSource(), ChromaConstant(6.0)),
             n2 = TonalSpec(HueSource(), ChromaConstant(8.0))
     )),
     VIBRANT(CoreSpec(
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 ab4aca5..babe5700 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -112,6 +112,9 @@
     /** Call whenever the color palette should update */
     fun onColorPaletteChanged(resources: Resources) {}
 
+    /** Call if the seed color has changed and should be updated */
+    fun onSeedColorChanged(seedColor: Int?) {}
+
     /** Call whenever the weather data should update */
     fun onWeatherDataChanged(data: WeatherData) {}
 }
@@ -189,12 +192,13 @@
     val clockId: ClockId? = null,
     val seedColor: Int? = null,
 ) {
-    var _applied_timestamp: Long? = null
+    // Exclude metadata from equality checks
+    var metadata: JSONObject = JSONObject()
 
     companion object {
         private val KEY_CLOCK_ID = "clockId"
         private val KEY_SEED_COLOR = "seedColor"
-        private val KEY_TIMESTAMP = "_applied_timestamp"
+        private val KEY_METADATA = "metadata"
 
         fun serialize(setting: ClockSettings?): String {
             if (setting == null) {
@@ -204,7 +208,7 @@
             return JSONObject()
                 .put(KEY_CLOCK_ID, setting.clockId)
                 .put(KEY_SEED_COLOR, setting.seedColor)
-                .put(KEY_TIMESTAMP, setting._applied_timestamp)
+                .put(KEY_METADATA, setting.metadata)
                 .toString()
         }
 
@@ -216,11 +220,11 @@
             val json = JSONObject(jsonStr)
             val result =
                 ClockSettings(
-                    json.getString(KEY_CLOCK_ID),
+                    if (!json.isNull(KEY_CLOCK_ID)) json.getString(KEY_CLOCK_ID) else null,
                     if (!json.isNull(KEY_SEED_COLOR)) json.getInt(KEY_SEED_COLOR) else null
                 )
-            if (!json.isNull(KEY_TIMESTAMP)) {
-                result._applied_timestamp = json.getLong(KEY_TIMESTAMP)
+            if (!json.isNull(KEY_METADATA)) {
+                result.metadata = json.getJSONObject(KEY_METADATA)
             }
             return result
         }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
index e99b214..3e34885 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
@@ -35,7 +35,6 @@
  * as the result of taking a bug report).
  *
  * You can dump the entire buffer at any time by running:
- *
  * ```
  * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService <bufferName>
  * ```
@@ -46,13 +45,11 @@
  * locally (usually for debugging purposes).
  *
  * To enable logcat echoing for an entire buffer:
- *
  * ```
  * $ adb shell settings put global systemui/buffer/<bufferName> <level>
  * ```
  *
  * To enable logcat echoing for a specific tag:
- *
  * ```
  * $ adb shell settings put global systemui/tag/<tag> <level>
  * ```
@@ -64,10 +61,10 @@
  * LogBufferFactory.
  *
  * @param name The name of this buffer, printed when the buffer is dumped and in some other
- * situations.
+ *   situations.
  * @param maxSize The maximum number of messages to keep in memory at any one time. Buffers start
- * out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches the
- * maximum, it behaves like a ring buffer.
+ *   out empty and grow up to [maxSize] as new messages are logged. Once the buffer's size reaches
+ *   the maximum, it behaves like a ring buffer.
  */
 class LogBuffer
 @JvmOverloads
@@ -116,22 +113,22 @@
      * initializer stored and converts it to a human-readable log message.
      *
      * @param tag A string of at most 23 characters, used for grouping logs into categories or
-     * subjects. If this message is echoed to logcat, this will be the tag that is used.
+     *   subjects. If this message is echoed to logcat, this will be the tag that is used.
      * @param level Which level to log the message at, both to the buffer and to logcat if it's
-     * echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
-     * INFO level should be reserved for information that other parts of the system might care
-     * about, leaving the specifics of code's day-to-day operations to DEBUG.
+     *   echoed. In general, a module should split most of its logs into either INFO or DEBUG level.
+     *   INFO level should be reserved for information that other parts of the system might care
+     *   about, leaving the specifics of code's day-to-day operations to DEBUG.
      * @param messageInitializer A function that will be called immediately to store relevant data
-     * on the log message. The value of `this` will be the LogMessage to be initialized.
+     *   on the log message. The value of `this` will be the LogMessage to be initialized.
      * @param messagePrinter A function that will be called if and when the message needs to be
-     * dumped to logcat or a bug report. It should read the data stored by the initializer and
-     * convert it to a human-readable string. The value of `this` will be the LogMessage to be
-     * printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
-     * NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
-     * new instance of the printer for each call, thwarting our attempts at avoiding any sort of
-     * allocation.
+     *   dumped to logcat or a bug report. It should read the data stored by the initializer and
+     *   convert it to a human-readable string. The value of `this` will be the LogMessage to be
+     *   printed. **IMPORTANT:** The printer should ONLY ever reference fields on the LogMessage and
+     *   NEVER any variables in its enclosing scope. Otherwise, the runtime will need to allocate a
+     *   new instance of the printer for each call, thwarting our attempts at avoiding any sort of
+     *   allocation.
      * @param exception Provide any exception that need to be logged. This is saved as
-     * [LogMessage.exception]
+     *   [LogMessage.exception]
      */
     @JvmOverloads
     inline fun log(
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
index faf1b78..7a125ac 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
@@ -28,7 +28,6 @@
  * Version of [LogcatEchoTracker] for debuggable builds
  *
  * The log level of individual buffers or tags can be controlled via global settings:
- *
  * ```
  * # Echo any message to <bufferName> of <level> or higher
  * $ adb shell settings put global systemui/buffer/<bufferName> <level>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
index 68d7890..4773f54 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/util/RingBuffer.kt
@@ -30,7 +30,7 @@
  *
  * @param maxSize The maximum size the buffer can grow to before it begins functioning as a ring.
  * @param factory A function that creates a fresh instance of T. Used by the buffer while it's
- * growing to [maxSize].
+ *   growing to [maxSize].
  */
 class RingBuffer<T>(private val maxSize: Int, private val factory: () -> T) : Iterable<T> {
 
diff --git a/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png
deleted file mode 100644
index 2e259c3..0000000
--- a/packages/SystemUI/res-keyguard/drawable-mdpi/ic_lockscreen_sim.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png
deleted file mode 100644
index f4de96a..0000000
--- a/packages/SystemUI/res-keyguard/drawable-xhdpi/ic_lockscreen_sim.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png b/packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png
similarity index 100%
rename from packages/SystemUI/res-keyguard/drawable-hdpi/ic_lockscreen_sim.png
rename to packages/SystemUI/res-keyguard/drawable/ic_lockscreen_sim.png
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml b/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml
deleted file mode 100644
index 4ff2967..0000000
--- a/packages/SystemUI/res-keyguard/layout/fsi_chrome_view.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<com.android.systemui.statusbar.notification.fsi.FsiChromeView android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_margin="50dp"
-    android:orientation="vertical"
-    xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:id="@+id/fsi_chrome"
-        android:layout_height="50dp"
-        android:orientation="horizontal">
-
-        <ImageView
-            android:id="@+id/fsi_app_icon"
-            android:layout_width="50dp"
-            android:layout_height="match_parent"
-            android:contentDescription="@null" />
-
-        <TextView
-            android:id="@+id/fsi_app_name"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:padding="10dp"
-            android:textSize="22dp"
-            android:gravity="center"
-            android:textColor="#FFFFFF"
-            android:text="AppName" />
-
-        <Space
-            android:layout_width="0dp"
-            android:layout_height="0dp"
-            android:layout_weight="1" />
-
-        <Button
-            android:id="@+id/fsi_fullscreen_button"
-            android:layout_width="100dp"
-            android:layout_height="match_parent"
-            android:text="fullscreen" />
-
-        <Button
-            android:id="@+id/fsi_dismiss_button"
-            android:layout_width="100dp"
-            android:layout_height="match_parent"
-            android:text="dismiss" />
-
-    </LinearLayout>
-
-</com.android.systemui.statusbar.notification.fsi.FsiChromeView>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
index 411fea5..48769fd 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_num_pad_key.xml
@@ -14,10 +14,12 @@
   ~ limitations under the License
   -->
 
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android" >
     <TextView
         android:id="@+id/digit_text"
         style="@style/Widget.TextView.NumPadKey.Digit"
+        android:autoSizeMaxTextSize="32sp"
+        android:autoSizeTextType="uniform"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index 7db0fe9..728d861 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
 **
 ** Copyright 2012, The Android Open Source Project
 **
@@ -17,185 +16,185 @@
 */
 -->
 <!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. -->
-<com.android.keyguard.KeyguardSimPinView
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:androidprv="http://schemas.android.com/apk/res-auto"
-        android:id="@+id/keyguard_sim_pin_view"
-        android:orientation="vertical"
+<com.android.keyguard.KeyguardSimPinView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/keyguard_sim_pin_view"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    androidprv:layout_maxWidth="@dimen/keyguard_security_width"
+    android:layout_gravity="center_horizontal|bottom">
+    <include layout="@layout/keyguard_bouncer_message_area"/>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        androidprv:layout_maxWidth="@dimen/keyguard_security_width"
-        android:layout_gravity="center_horizontal|bottom">
-    <include layout="@layout/keyguard_bouncer_message_area" />
-    <Space
-          android:layout_width="match_parent"
-          android:layout_height="0dp"
-          android:layout_weight="1" />
-    <ImageView
-            android:id="@+id/keyguard_sim"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:tint="@color/background_protected"
-            android:src="@drawable/ic_lockscreen_sim"/>
-    <LinearLayout
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        android:layoutDirection="ltr">
+        <LinearLayout
+            android:id="@+id/pin_area"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:gravity="center"
-            android:layoutDirection="ltr"
-            >
-        <include layout="@layout/keyguard_esim_area"
-             android:id="@+id/keyguard_esim_area"
-             android:layout_width="wrap_content"
-             android:layout_height="wrap_content" />
-        <RelativeLayout
-                android:id="@+id/row0"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingBottom="4dp"
-                >
+            android:gravity="center_horizontal"
+            android:paddingTop="@dimen/num_pad_entry_row_margin_bottom"
+            android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+            androidprv:layout_constraintBottom_toTopOf="@+id/flow1"
+            androidprv:layout_constraintEnd_toEndOf="parent"
+            androidprv:layout_constraintStart_toStartOf="parent"
+            androidprv:layout_constraintTop_toTopOf="parent">
+
+            <ImageView
+                android:id="@+id/keyguard_sim"
+                android:layout_width="40dp"
+                android:layout_height="40dp"
+                android:layout_gravity="center_horizontal"
+                android:src="@drawable/ic_lockscreen_sim"
+                app:tint="@color/background_protected" />
+
+            <include
+                android:id="@+id/keyguard_esim_area"
+                layout="@layout/keyguard_esim_area"
+                android:layout_gravity="center_horizontal"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+
             <com.android.keyguard.PasswordTextView
                 android:id="@+id/simPinEntry"
                 style="@style/Widget.TextView.Password"
                 android:layout_width="@dimen/keyguard_security_width"
                 android:layout_height="@dimen/keyguard_password_height"
-                android:layout_centerHorizontal="true"
-                android:layout_marginRight="72dp"
                 android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
-                android:gravity="center"
+                android:layout_gravity="center_horizontal"
                 androidprv:scaledTextSize="@integer/scaled_password_text_size" />
-        </RelativeLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key1"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="1"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key2"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="2"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key3"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="3"
-                    />
         </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key4"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="4"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key5"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="5"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key6"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="6"
-                    />
-        </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key7"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="7"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key8"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="8"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key9"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="9"
-                    />
-        </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                >
-            <com.android.keyguard.NumPadButton
-                    android:id="@+id/delete_button"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    android:contentDescription="@string/keyboardview_keycode_delete"
-                    style="@style/NumPadKey.Delete"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key0"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/simPinEntry"
-                    androidprv:digit="0"
-                    />
-            <com.android.keyguard.NumPadButton
-                    android:id="@+id/key_enter"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    style="@style/NumPadKey.Enter"
-                    android:contentDescription="@string/keyboardview_keycode_enter"
-                    />
-        </LinearLayout>
-    </LinearLayout>
-    <include layout="@layout/keyguard_eca"
-             android:id="@+id/keyguard_selector_fade_container"
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-             android:orientation="vertical"
-             android:layout_gravity="bottom|center_horizontal"
-             android:layout_marginTop="@dimen/keyguard_eca_top_margin"
-             android:layout_marginBottom="2dp"
-             android:gravity="center_horizontal"/>
+
+        <androidx.constraintlayout.helper.widget.Flow
+            android:id="@+id/flow1"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:orientation="horizontal"
+            androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+            androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+            androidprv:flow_horizontalStyle="packed"
+            androidprv:flow_maxElementsWrap="3"
+            androidprv:flow_verticalBias="1.0"
+            androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+            androidprv:flow_verticalStyle="packed"
+            androidprv:flow_wrapMode="aligned"
+            androidprv:layout_constraintBottom_toBottomOf="parent"
+            androidprv:layout_constraintEnd_toEndOf="parent"
+            androidprv:layout_constraintStart_toStartOf="parent"
+            androidprv:layout_constraintTop_toBottomOf="@id/pin_area" />
+
+        <com.android.keyguard.NumPadButton
+            android:id="@+id/delete_button"
+            style="@style/NumPadKey.Delete"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key0"
+            android:contentDescription="@string/keyboardview_keycode_delete" />
+
+        <com.android.keyguard.NumPadButton
+            android:id="@+id/key_enter"
+            style="@style/NumPadKey.Enter"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:contentDescription="@string/keyboardview_keycode_enter" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key1"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key2"
+            androidprv:digit="1"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key2"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key3"
+            androidprv:digit="2"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key3"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key4"
+            androidprv:digit="3"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key4"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key5"
+            androidprv:digit="4"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key5"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key6"
+            androidprv:digit="5"
+            androidprv:textView="@+id/simPinEntry" />
+
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key6"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key7"
+            androidprv:digit="6"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key7"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key8"
+            androidprv:digit="7"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <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/simPinEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key9"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/delete_button"
+            androidprv:digit="9"
+            androidprv:textView="@+id/simPinEntry" />
+
+        <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/simPinEntry" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <include
+        android:id="@+id/keyguard_selector_fade_container"
+        layout="@layout/keyguard_eca"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom|center_horizontal"
+        android:layout_marginBottom="2dp"
+        android:layout_marginTop="@dimen/keyguard_eca_top_margin"
+        android:gravity="center_horizontal"
+        android:orientation="vertical" />
 </com.android.keyguard.KeyguardSimPinView>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 422bd4c..7e24d12 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -21,6 +21,7 @@
 <com.android.keyguard.KeyguardSimPukView
         xmlns:android="http://schemas.android.com/apk/res/android"
         xmlns:androidprv="http://schemas.android.com/apk/res-auto"
+        xmlns:app="http://schemas.android.com/apk/res-auto"
         android:id="@+id/keyguard_sim_puk_view"
         android:orientation="vertical"
         android:layout_width="match_parent"
@@ -29,173 +30,165 @@
         android:layout_gravity="center_horizontal|bottom">
     <include layout="@layout/keyguard_bouncer_message_area"/>
 
-    <Space
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
         android:layout_height="0dp"
-        android:layout_weight="1" />
-
-    <ImageView
-            android:id="@+id/keyguard_sim"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:tint="@color/background_protected"
-            android:src="@drawable/ic_lockscreen_sim"/>
-
-    <LinearLayout
+        android:layout_weight="1"
+        android:layoutDirection="ltr">
+        <LinearLayout
+            android:id="@+id/pin_area"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="vertical"
-            android:gravity="center"
-            android:layoutDirection="ltr"
-            >
-        <include layout="@layout/keyguard_esim_area"
-            android:id="@+id/keyguard_esim_area"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
+            android:gravity="center_horizontal"
+            android:paddingTop="@dimen/num_pad_entry_row_margin_bottom"
+            android:paddingBottom="@dimen/num_pad_entry_row_margin_bottom"
+            androidprv:layout_constraintBottom_toTopOf="@+id/flow1"
+            androidprv:layout_constraintEnd_toEndOf="parent"
+            androidprv:layout_constraintStart_toStartOf="parent"
+            androidprv:layout_constraintTop_toTopOf="parent">
 
-        <RelativeLayout
-                android:id="@+id/row0"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingBottom="4dp"
-                >
+            <ImageView
+                android:id="@+id/keyguard_sim"
+                android:layout_width="40dp"
+                android:layout_height="40dp"
+                android:layout_gravity="center_horizontal"
+                android:src="@drawable/ic_lockscreen_sim"
+                app:tint="@color/background_protected" />
+
+            <include
+                android:id="@+id/keyguard_esim_area"
+                layout="@layout/keyguard_esim_area"
+                android:layout_gravity="center_horizontal"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
 
             <com.android.keyguard.PasswordTextView
                 android:id="@+id/pukEntry"
                 style="@style/Widget.TextView.Password"
                 android:layout_width="@dimen/keyguard_security_width"
                 android:layout_height="@dimen/keyguard_password_height"
-                android:layout_centerHorizontal="true"
-                android:layout_marginRight="72dp"
-                android:contentDescription="@string/keyguard_accessibility_sim_puk_area"
-                android:gravity="center"
+                android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
+                android:layout_gravity="center_horizontal"
                 androidprv:scaledTextSize="@integer/scaled_password_text_size" />
-        </RelativeLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key1"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="1"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key2"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="2"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key3"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="3"
-                    />
         </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
 
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key4"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="4"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key5"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="5"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key6"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="6"
-                    />
-        </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                android:layout_marginBottom="@dimen/num_pad_row_margin_bottom"
-                >
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key7"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="7"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key8"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="8"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key9"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="9"
-                    />
-        </LinearLayout>
-        <LinearLayout
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                android:layout_gravity="center_horizontal"
-                >
-            <com.android.keyguard.NumPadButton
-                    android:id="@+id/delete_button"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    android:contentDescription="@string/keyboardview_keycode_delete"
-                    style="@style/NumPadKey.Delete"
-                    />
-            <com.android.keyguard.NumPadKey
-                    android:id="@+id/key0"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginEnd="@dimen/num_pad_key_margin_end"
-                    androidprv:textView="@+id/pukEntry"
-                    androidprv:digit="0"
-                    />
-            <com.android.keyguard.NumPadButton
-                    android:id="@+id/key_enter"
-                    android:layout_width="@dimen/num_pad_key_width"
-                    android:layout_height="match_parent"
-                    style="@style/NumPadKey.Enter"
-                    android:contentDescription="@string/keyboardview_keycode_enter"
-                    />
-        </LinearLayout>
-    </LinearLayout>
+        <androidx.constraintlayout.helper.widget.Flow
+            android:id="@+id/flow1"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:clipChildren="false"
+            android:clipToPadding="false"
+            android:orientation="horizontal"
+            androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter"
+            androidprv:flow_horizontalGap="@dimen/num_pad_key_margin_end"
+            androidprv:flow_horizontalStyle="packed"
+            androidprv:flow_maxElementsWrap="3"
+            androidprv:flow_verticalBias="1.0"
+            androidprv:flow_verticalGap="@dimen/num_pad_entry_row_margin_bottom"
+            androidprv:flow_verticalStyle="packed"
+            androidprv:flow_wrapMode="aligned"
+            androidprv:layout_constraintBottom_toBottomOf="parent"
+            androidprv:layout_constraintEnd_toEndOf="parent"
+            androidprv:layout_constraintStart_toStartOf="parent"
+            androidprv:layout_constraintTop_toBottomOf="@id/pin_area" />
+
+        <com.android.keyguard.NumPadButton
+            android:id="@+id/delete_button"
+            style="@style/NumPadKey.Delete"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key0"
+            android:contentDescription="@string/keyboardview_keycode_delete" />
+
+        <com.android.keyguard.NumPadButton
+            android:id="@+id/key_enter"
+            style="@style/NumPadKey.Enter"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:contentDescription="@string/keyboardview_keycode_enter" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key1"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key2"
+            androidprv:digit="1"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key2"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key3"
+            androidprv:digit="2"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key3"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key4"
+            androidprv:digit="3"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key4"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key5"
+            androidprv:digit="4"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key5"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key6"
+            androidprv:digit="5"
+            androidprv:textView="@+id/pukEntry" />
+
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key6"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key7"
+            androidprv:digit="6"
+            androidprv:textView="@+id/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key7"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/key8"
+            androidprv:digit="7"
+            androidprv:textView="@+id/pukEntry" />
+
+        <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/pukEntry" />
+
+        <com.android.keyguard.NumPadKey
+            android:id="@+id/key9"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:accessibilityTraversalBefore="@id/delete_button"
+            androidprv:digit="9"
+            androidprv:textView="@+id/pukEntry" />
+
+        <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/pukEntry" />
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
     <include layout="@layout/keyguard_eca"
              android:id="@+id/keyguard_selector_fade_container"
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index ce88d5b..6a18b3d 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -31,8 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzea optimizatu da bateria ez kaltetzeko"</string>
-    <!-- no translation found for keyguard_plugged_in_incompatible_charger (5712938022567388098) -->
-    <skip />
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargagailua ez da bateragarria"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Ez dago SIMik"</string>
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index 80bd0bf..2f295f7 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -31,8 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge optimisée pour protéger la pile"</string>
-    <!-- no translation found for keyguard_plugged_in_incompatible_charger (5712938022567388098) -->
-    <skip />
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • chargeur incompatible"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"Aucune carte SIM"</string>
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index b2058a1..9dd5c5d 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -31,8 +31,7 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="1053130519456324630">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 배터리 보호를 위해 충전 최적화됨"</string>
-    <!-- no translation found for keyguard_plugged_in_incompatible_charger (5712938022567388098) -->
-    <skip />
+    <string name="keyguard_plugged_in_incompatible_charger" msgid="5712938022567388098">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 호환되지 않는 충전기"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"잠금 해제하려면 메뉴를 누르세요."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string>
     <string name="keyguard_missing_sim_message_short" msgid="685029586173458728">"SIM 없음"</string>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index b6a78f5..caf3233 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -82,7 +82,7 @@
     <!-- The vertical margin between the date and the owner info. -->
 
     <!-- The translation for disappearing security views after having solved them. -->
-    <dimen name="disappear_y_translation">-32dp</dimen>
+    <dimen name="disappear_y_translation">-50dp</dimen>
 
     <!-- Dimens for animation for the Bouncer PIN view -->
     <dimen name="pin_view_trans_y_entry">120dp</dimen>
diff --git a/packages/SystemUI/res/drawable/controls_panel_background.xml b/packages/SystemUI/res/drawable/controls_panel_background.xml
index 9092877..fc108a5 100644
--- a/packages/SystemUI/res/drawable/controls_panel_background.xml
+++ b/packages/SystemUI/res/drawable/controls_panel_background.xml
@@ -18,5 +18,5 @@
 
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
     <solid android:color="#1F1F1F" />
-    <corners android:radius="@dimen/notification_corner_radius" />
+    <corners android:radius="@dimen/controls_panel_corner_radius" />
 </shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml b/packages/SystemUI/res/drawable/qs_footer_edit_circle.xml
new file mode 100644
index 0000000..2e29cae
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_footer_edit_circle.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.
+  -->
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+       android:inset="@dimen/qs_footer_action_inset">
+    <ripple
+        android:color="?android:attr/colorControlHighlight">
+        <item android:id="@android:id/mask">
+            <!-- We make this shape a rounded rectangle instead of a oval so that it can animate -->
+            <!-- properly into an app/dialog. -->
+            <shape android:shape="rectangle">
+                <solid android:color="@android:color/white"/>
+                <corners android:radius="@dimen/qs_footer_action_corner_radius"/>
+            </shape>
+        </item>
+        <item>
+            <shape android:shape="rectangle">
+                <corners android:radius="@dimen/qs_footer_action_corner_radius"/>
+            </shape>
+        </item>
+
+    </ripple>
+</inset>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/controls_fullscreen.xml b/packages/SystemUI/res/layout/controls_fullscreen.xml
index e08e63b..fa70303 100644
--- a/packages/SystemUI/res/layout/controls_fullscreen.xml
+++ b/packages/SystemUI/res/layout/controls_fullscreen.xml
@@ -15,19 +15,11 @@
      limitations under the License.
 -->
 
-<FrameLayout
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/control_detail_root"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical">
 
-
-    <LinearLayout
-        android:id="@+id/global_actions_controls"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:paddingHorizontal="@dimen/controls_padding_horizontal" />
-
-</FrameLayout>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml
index aa211bf..71561c0 100644
--- a/packages/SystemUI/res/layout/controls_with_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_with_favorites.xml
@@ -13,82 +13,94 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<merge
-    xmlns:android="http://schemas.android.com/apk/res/android">
+<merge xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:orientation="vertical"
+    tools:parentTag="android.widget.LinearLayout">
 
-  <LinearLayout
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content"
-      android:orientation="horizontal"
-      android:layout_marginBottom="@dimen/controls_header_bottom_margin">
-
-    <!-- make sure the header stays centered in the layout by adding a spacer -->
-    <Space
-        android:id="@+id/controls_spacer"
-        android:layout_width="@dimen/controls_header_menu_size"
-        android:layout_height="1dp"
-        android:visibility="gone" />
-
-    <ImageView
-        android:id="@+id/controls_close"
-        android:contentDescription="@string/accessibility_desc_close"
-        android:src="@drawable/ic_close"
-        android:background="?android:attr/selectableItemBackgroundBorderless"
-        android:tint="@color/control_primary_text"
-        android:layout_width="@dimen/controls_header_menu_size"
-        android:layout_height="@dimen/controls_header_menu_size"
-        android:padding="12dp"
-        android:visibility="gone" />
-    <!-- need to keep this outer view in order to have a correctly sized anchor
-         for the dropdown menu, as well as dropdown background in the right place -->
     <LinearLayout
-        android:id="@+id/controls_header"
-        android:orientation="horizontal"
-        android:layout_width="0dp"
-        android:layout_weight="1"
-        android:minHeight="48dp"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:gravity="center">
-      <TextView
-          style="@style/Control.Spinner.Header"
-          android:clickable="false"
-          android:id="@+id/app_or_structure_spinner"
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:layout_gravity="center" />
-    </LinearLayout>
-    <ImageView
-        android:id="@+id/controls_more"
-        android:src="@drawable/ic_more_vert"
-        android:layout_width="@dimen/controls_header_menu_size"
-        android:layout_height="@dimen/controls_header_menu_size"
-        android:padding="12dp"
-        android:tint="@color/control_more_vert"
-        android:layout_gravity="center"
-        android:contentDescription="@string/accessibility_menu"
-        android:background="?android:attr/selectableItemBackgroundBorderless" />
-  </LinearLayout>
+        android:paddingHorizontal="@dimen/controls_header_horizontal_padding"
+        android:layout_marginBottom="@dimen/controls_header_bottom_margin"
+        android:orientation="horizontal">
 
-  <ScrollView
+        <!-- make sure the header stays centered in the layout by adding a spacer -->
+        <Space
+            android:id="@+id/controls_spacer"
+            android:layout_width="@dimen/controls_header_menu_button_size"
+            android:layout_height="1dp"
+            android:visibility="gone" />
+
+        <ImageView
+            android:id="@+id/controls_close"
+            android:layout_width="@dimen/controls_header_menu_button_size"
+            android:layout_height="@dimen/controls_header_menu_button_size"
+            android:layout_gravity="center_vertical"
+            android:background="?android:attr/selectableItemBackgroundBorderless"
+            android:contentDescription="@string/accessibility_desc_close"
+            android:padding="12dp"
+            android:src="@drawable/ic_close"
+            android:tint="@color/control_primary_text"
+            android:visibility="gone"
+            tools:visibility="visible" />
+
+        <!-- need to keep this outer view in order to have a correctly sized anchor
+             for the dropdown menu, as well as dropdown background in the right place -->
+        <LinearLayout
+            android:id="@+id/controls_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:minHeight="48dp"
+            android:orientation="horizontal">
+
+            <TextView
+                android:id="@+id/app_or_structure_spinner"
+                style="@style/Control.Spinner.Header"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:clickable="false"
+                tools:text="Test app" />
+        </LinearLayout>
+
+        <ImageView
+            android:id="@+id/controls_more"
+            android:layout_width="@dimen/controls_header_menu_button_size"
+            android:layout_height="@dimen/controls_header_menu_button_size"
+            android:layout_gravity="center_vertical"
+            android:background="?android:attr/selectableItemBackgroundBorderless"
+            android:contentDescription="@string/accessibility_menu"
+            android:padding="12dp"
+            android:src="@drawable/ic_more_vert"
+            android:tint="@color/control_more_vert" />
+    </LinearLayout>
+
+    <ScrollView
         android:id="@+id/controls_scroll_view"
         android:layout_width="match_parent"
         android:layout_height="0dp"
+        android:layout_marginHorizontal="@dimen/controls_content_margin_horizontal"
         android:layout_weight="1"
-        android:orientation="vertical"
         android:clipChildren="true"
+        android:orientation="vertical"
         android:paddingHorizontal="16dp"
         android:scrollbars="none">
-    <include layout="@layout/global_actions_controls_list_view" />
 
-  </ScrollView>
+        <include layout="@layout/global_actions_controls_list_view" />
 
-  <FrameLayout
-      android:id="@+id/controls_panel"
-      android:layout_width="match_parent"
-      android:layout_height="0dp"
-      android:layout_weight="1"
-      android:background="@drawable/controls_panel_background"
-      android:visibility="gone"
-      />
+    </ScrollView>
+
+    <FrameLayout
+        android:id="@+id/controls_panel"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_marginHorizontal="@dimen/controls_content_margin_horizontal"
+        android:layout_weight="1"
+        android:background="@drawable/controls_panel_background"
+        android:visibility="gone"
+        tools:visibility="visible" />
 </merge>
diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml
index b1d3ed05..745cfc6 100644
--- a/packages/SystemUI/res/layout/qs_footer_impl.xml
+++ b/packages/SystemUI/res/layout/qs_footer_impl.xml
@@ -64,7 +64,7 @@
                     android:layout_width="@dimen/qs_footer_action_button_size"
                     android:layout_height="@dimen/qs_footer_action_button_size"
                     android:layout_gravity="center_vertical|end"
-                    android:background="?android:attr/selectableItemBackground"
+                    android:background="@drawable/qs_footer_edit_circle"
                     android:clickable="true"
                     android:contentDescription="@string/accessibility_quick_settings_edit"
                     android:focusable="true"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index be9ef9d..f265426 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kennisgewingskerm."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Vinnige instellings."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kitsinstellings en kennisgewingskerm."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Sluitskerm."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Werksluitskerm"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Maak toe"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 03925f7..4ec413e 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"مركز الإشعارات."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"الإعدادات السريعة."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"\"الإعدادات السريعة\" و\"مركز الإشعارات\""</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"شاشة القفل."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"شاشة قفل بيانات العمل"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"إغلاق"</string>
@@ -695,7 +694,7 @@
     <string name="right_keycode" msgid="2480715509844798438">"رمز مفتاح اليمين"</string>
     <string name="left_icon" msgid="5036278531966897006">"رمز اليسار"</string>
     <string name="right_icon" msgid="1103955040645237425">"رمز اليمين"</string>
-    <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة الميزات."</string>
+    <string name="drag_to_add_tiles" msgid="8933270127508303672">"اضغط باستمرار مع السحب لإضافة المربّعات"</string>
     <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"اضغط باستمرار مع السحب لإعادة ترتيب الميزات."</string>
     <string name="drag_to_remove_tiles" msgid="4682194717573850385">"اسحب هنا للإزالة"</string>
     <string name="drag_to_remove_disabled" msgid="933046987838658850">"الحدّ الأدنى من عدد المربعات الذي تحتاج إليه هو <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g>"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"التبديل إلى الملف الشخصي للعمل"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"إغلاق"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"إعدادات شاشة القفل"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"‏لا يتوفّر اتصال Wi-Fi."</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"استخدام الكاميرا محظور."</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"استخدام الكاميرا والميكروفون محظور."</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"استخدام الميكروفون محظور."</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"وضع الأولوية مفعّل."</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"‏ميزة لفت انتباه \"مساعد Google\" مفعّلة."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 9507cda..ae2f1e2 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"জাননী পেনেল।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ক্ষিপ্ৰ ছেটিং।"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ক্ষিপ্ৰ ছেটিং জাননী পেনেল।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"বন্ধ স্ক্ৰীন।"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কৰ্মস্থানৰ প্ৰ\'ফাইলৰ লক স্ক্ৰীন"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ কৰক"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index fcee2e1..3349674 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildiriş kölgəsi."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tez ayarlar."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Sürətli ayarlar və Bildiriş göstərişi."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kilid ekranı."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran kilidi"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Qapadın"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 12ce259..dbfb012 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Цень апавяшчэння.."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Хуткія налады."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Хуткія налады і шчыток апавяшчэнняў."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Экран блакіроўкі."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Экран блакіроўкі дзейнасці"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыць"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Пераключыцца на працоўны профіль"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрыць"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Налады экрана блакіроўкі"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Сетка Wi-Fi недаступная"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера заблакіравана"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера і мікрафон заблакіраваны"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрафон заблакіраваны"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Прыярытэтны рэжым уключаны"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Памочнік гатовы выконваць каманды"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 9ba041e..e87b628 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Падащ панел с известия."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Бързи настройки."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Падащ панел с бързи настройки и известия."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заключване на екрана."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Заключен екран на служебния профил"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Затваряне"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index dbc3a52..2a84e59 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"বিজ্ঞপ্তি শেড৷"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"দ্রুত সেটিংস৷"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"দ্রুত সেটিংস এবং বিজ্ঞপ্তি শেড।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"লক স্ক্রিন।"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"কর্মস্থলের স্ক্রিন লক"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"বন্ধ করুন"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"অফিস প্রোফাইলে পাল্টে নিন"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"বন্ধ করুন"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"লক স্ক্রিন সেটিংস"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ওয়াই-ফাই উপলভ্য নয়"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ক্যামেরার অ্যাক্সেস ব্লক করা আছে"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ক্যামেরা এবং মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"মাইক্রোফোনের অ্যাক্সেস ব্লক করা আছে"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\'প্রায়োরিটি\' মোড চালু করা আছে"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"অ্যাসিস্ট্যান্ট আপনার কথা শোনার জন্য চালু করা আছে"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 8d4a0dd..e73eab9 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -198,7 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obavještenja sa sjenčenjem."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Brze postavke."</string>
-    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i zaslon obavijesti."</string>
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Brze postavke i lokacija za obavještenja."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaključan ekran."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran radnog profila"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index cc87895..66d20e4 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Àrea de notificacions"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuració ràpida"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuració ràpida i àrea de notificacions."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueig"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueig per a la feina"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Tanca"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Configuració pantalla de bloqueig"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"No hi ha cap Wi‑Fi disponible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La càmera està bloquejada"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La càmera i el micròfon estan bloquejats"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micròfon està bloquejat"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El mode Prioritat està activat"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'Assistent està activat"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index e07a892..e61a4d0 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel oznámení."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rychlé nastavení."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Rychlé nastavení a panel oznámení"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Obrazovka uzamčení"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Obrazovka uzamčení pracovního profilu"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zavřít"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 4b10ddf..aa6a480 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notifikationspanel."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kvikmenu."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kvikmenu og notifikationspanel."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låseskærm."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låseskærm til arbejde"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Luk"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Skift til arbejdsprofil"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Luk"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Indstillinger for låseskærm"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ikke tilgængeligt"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kameraet er blokeret"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Der er blokeret for kameraet og mikrofonen"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofonen er blokeret"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritetstilstand er aktiveret"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent lytter"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index f8c02e3..621788a 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Benachrichtigungsleiste"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Schnelleinstellungen"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Schnelleinstellungen und Benachrichtigungsleiste."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Sperrbildschirm"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Sperrbildschirm für Arbeitsprofil"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Schließen"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f2fb5b8..d81cedb 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Πλαίσιο σκίασης ειδοποιήσεων."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Γρήγορες ρυθμίσεις."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Γρήγορες ρυθμίσεις και πλαίσιο σκίασης ειδοποιήσεων."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Οθόνη κλειδώματος"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Οθόνη κλειδωμένης εργασίας"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Κλείσιμο"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 81682b5..44b56de 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuración rápida y panel de notificaciones."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla bloqueada del perfil de trabajo"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Cerrar"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Config. de pantalla de bloqueo"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi no disponible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"La cámara está bloqueada"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"La cámara y el micrófono están bloqueados"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"El micrófono está bloqueado"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"El modo de prioridad está activado"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistente está prestando atención"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 526743a..9080c58 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pantalla de notificaciones"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ajustes rápidos"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ajustes rápidos y pantalla de notificaciones."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueo para el perfil de trabajo"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Cerrar"</string>
@@ -1019,7 +1018,7 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string>
-    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string>
+    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectado temporalmente"</string>
     <string name="mobile_data_poor_connection" msgid="819617772268371434">"Conexión inestable"</string>
     <string name="mobile_data_off_summary" msgid="3663995422004150567">"Los datos móviles no se conectarán automáticamente"</string>
     <string name="mobile_data_no_connection" msgid="1713872434869947377">"Sin conexión"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Ajustes de pantalla de bloqueo"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Red Wi-Fi no disponible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Cámara bloqueada"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Cámara y micrófono bloqueados"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrófono bloqueado"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modo Prioridad activado"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"El Asistente está activado"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 9388a14..9ce7dbf 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Märguande vari."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Kiirseaded."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Kiirseaded ja märguandeala."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kuva lukustamine."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Töö lukustuskuva"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Sulgemine"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Lukustuskuva seaded"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi pole saadaval"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kaamera on blokeeritud"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kaamera ja mikrofon on blokeeritud"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon on blokeeritud"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioriteetne režiim on sisse lülitatud"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistent on aktiveeritud"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 84f2d0c..d37afba 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -616,84 +616,48 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Jakinarazpenak"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Lasterbideak"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Aldatu tekl. diseinua"</string>
-    <!-- no translation found for keyboard_shortcut_clear_text (4679927133259287577) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_title (1156178106617830429) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_hint (5982623262974326746) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_no_result (6819302191660875501) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_system (1151182120757052669) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_input (5440558509904296233) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_open_apps (1450959949739257562) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_current_app (2011953559133734491) -->
-    <skip />
-    <!-- no translation found for group_system_access_notification_shade (7116898151485382275) -->
-    <skip />
-    <!-- no translation found for group_system_full_screenshot (7389040853798023211) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_app_shortcuts (4421497579210445641) -->
-    <skip />
-    <!-- no translation found for group_system_go_back (8838454003680364227) -->
-    <skip />
-    <!-- no translation found for group_system_access_home_screen (1857344316928441909) -->
-    <skip />
-    <!-- no translation found for group_system_overview_open_apps (6897128761003265350) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_forward (9202444850838205990) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_back (5163464503638229131) -->
-    <skip />
-    <!-- no translation found for group_system_access_all_apps_search (488070738028991753) -->
-    <skip />
-    <!-- no translation found for group_system_hide_reshow_taskbar (3809304065624351131) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_settings (7961639365383008053) -->
-    <skip />
-    <!-- no translation found for group_system_access_google_assistant (1186152943161483864) -->
-    <skip />
-    <!-- no translation found for group_system_lock_screen (7391191300363416543) -->
-    <skip />
-    <!-- no translation found for group_system_quick_memo (2914234890158583919) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_system_multitasking (1065232949510862593) -->
-    <skip />
-    <!-- no translation found for system_multitasking_rhs (6593269428880305699) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (8839380725557952846) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (1962084334200006297) -->
-    <skip />
-    <!-- no translation found for system_multitasking_replace (844285282472557186) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_input (6888282716546625610) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_next (3394291576873633793) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_previous (8823659252918609216) -->
-    <skip />
-    <!-- no translation found for input_access_emoji (8105642858900406351) -->
-    <skip />
-    <!-- no translation found for input_access_voice_typing (7291201476395326141) -->
-    <skip />
+    <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Garbitu testua"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Lasterbideak"</string>
+    <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Bilatu lasterbideak"</string>
+    <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Ez da aurkitu lasterbiderik"</string>
+    <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Sistema"</string>
+    <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Sarrera"</string>
+    <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Irekitako aplikazioak"</string>
+    <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Uneko aplikazioa"</string>
+    <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Atzitu jakinarazpenen panela"</string>
+    <string name="group_system_full_screenshot" msgid="7389040853798023211">"Atera pantaila osoaren argazki bat"</string>
+    <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Atzitu sistemaren edo aplikazioetarako lasterbideen zerrenda"</string>
+    <string name="group_system_go_back" msgid="8838454003680364227">"Atzera: itzuli aurreko egoerara (atzera egiteko botoia)"</string>
+    <string name="group_system_access_home_screen" msgid="1857344316928441909">"Atzitu hasierako pantaila"</string>
+    <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Ikusi irekitako aplikazioen ikuspegi orokorra"</string>
+    <string name="group_system_cycle_forward" msgid="9202444850838205990">"Joan azken aplikazioetako batetik bestera (aurrera)"</string>
+    <string name="group_system_cycle_back" msgid="5163464503638229131">"Joan azken aplikazioetako batetik bestera (atzera)"</string>
+    <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Atzitu aplikazio guztien zerrenda eta bilatu (adibidez, bilatzeko aukeraren edo Exekutatzeko tresna aplikazioaren bidez)"</string>
+    <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Ezkutatu eta erakutsi (berriro) zereginen barra"</string>
+    <string name="group_system_access_system_settings" msgid="7961639365383008053">"Atzitu sistemaren ezarpenak"</string>
+    <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Atzitu Google-ren Laguntzailea"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"Blokeatu pantaila"</string>
+    <string name="group_system_quick_memo" msgid="2914234890158583919">"Ireki Oharrak aplikazioa oharrak bizkor idazteko"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Zereginen aldibereko sistemaren exekuzioa"</string>
+    <string name="system_multitasking_rhs" msgid="6593269428880305699">"Sartu pantaila zatituaren eskuineko aldean uneko aplikazioarekin"</string>
+    <string name="system_multitasking_lhs" msgid="8839380725557952846">"Sartu pantaila zatituaren ezkerreko aldean uneko aplikazioarekin"</string>
+    <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Aldatu pantaila zatitutik pantaila osora"</string>
+    <string name="system_multitasking_replace" msgid="844285282472557186">"Pantaila zatituan zaudela: ordeztu aplikazio bat beste batekin"</string>
+    <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Sarrera"</string>
+    <string name="input_switch_input_language_next" msgid="3394291576873633793">"Aldatu idazteko hizkuntza (hurrengo hizkuntza)"</string>
+    <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Aldatu idazteko hizkuntza (aurreko hizkuntza)"</string>
+    <string name="input_access_emoji" msgid="8105642858900406351">"Atzitu emojiak"</string>
+    <string name="input_access_voice_typing" msgid="7291201476395326141">"Atzitu ahozko idazketa"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Aplikazioak"</string>
     <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Laguntzailea"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_browser (7328131901589876868) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Ireki arakatzailea (Chrome, modu lehenetsian)"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Kontaktuak"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_email (7480359963463803511) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Ireki posta elektronikoa (Gmail, modu lehenetsian)"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMSak"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musika"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_calculator (6316043911946540137) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_applications_maps (7312554713993114342) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Ireki Kalkulagailua"</string>
+    <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Ireki Maps"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ez molestatzeko modua"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"Bolumen-botoietarako lasterbidea"</string>
     <string name="battery" msgid="769686279459897127">"Bateria"</string>
@@ -856,12 +820,9 @@
     <string name="privacy_type_media_projection" msgid="8136723828804251547">"pantaila-grabaketa"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Ez du izenik"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Egonean"</string>
-    <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
-    <skip />
-    <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
-    <skip />
-    <!-- no translation found for font_scaling_larger (5476242157436806760) -->
-    <skip />
+    <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Letraren tamaina"</string>
+    <string name="font_scaling_smaller" msgid="1012032217622008232">"Txikitu"</string>
+    <string name="font_scaling_larger" msgid="5476242157436806760">"Handitu"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Lupa-leihoa"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"Lupa-leihoaren aukerak"</string>
     <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Handitu"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index bafee64..9bc513e 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"مجموعه اعلان."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"تنظیمات سریع."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"تنظیمات فوری و کشوی اعلانات."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"صفحه قفل."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"صفحه قفل کاری"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"بستن"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4097e76..4c3962e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ilmoitusalue."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Pika-asetukset."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Pika-asetukset ja ilmoitusalue"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lukitse näyttö."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Työlukitusnäyttö"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Sulje"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 47974b2..05dec17 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -616,84 +616,48 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Notifications"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Raccourcis clavier"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Changer la disposition du clavier"</string>
-    <!-- no translation found for keyboard_shortcut_clear_text (4679927133259287577) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_title (1156178106617830429) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_hint (5982623262974326746) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_no_result (6819302191660875501) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_system (1151182120757052669) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_input (5440558509904296233) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_open_apps (1450959949739257562) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_current_app (2011953559133734491) -->
-    <skip />
-    <!-- no translation found for group_system_access_notification_shade (7116898151485382275) -->
-    <skip />
-    <!-- no translation found for group_system_full_screenshot (7389040853798023211) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_app_shortcuts (4421497579210445641) -->
-    <skip />
-    <!-- no translation found for group_system_go_back (8838454003680364227) -->
-    <skip />
-    <!-- no translation found for group_system_access_home_screen (1857344316928441909) -->
-    <skip />
-    <!-- no translation found for group_system_overview_open_apps (6897128761003265350) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_forward (9202444850838205990) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_back (5163464503638229131) -->
-    <skip />
-    <!-- no translation found for group_system_access_all_apps_search (488070738028991753) -->
-    <skip />
-    <!-- no translation found for group_system_hide_reshow_taskbar (3809304065624351131) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_settings (7961639365383008053) -->
-    <skip />
-    <!-- no translation found for group_system_access_google_assistant (1186152943161483864) -->
-    <skip />
-    <!-- no translation found for group_system_lock_screen (7391191300363416543) -->
-    <skip />
-    <!-- no translation found for group_system_quick_memo (2914234890158583919) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_system_multitasking (1065232949510862593) -->
-    <skip />
-    <!-- no translation found for system_multitasking_rhs (6593269428880305699) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (8839380725557952846) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (1962084334200006297) -->
-    <skip />
-    <!-- no translation found for system_multitasking_replace (844285282472557186) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_input (6888282716546625610) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_next (3394291576873633793) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_previous (8823659252918609216) -->
-    <skip />
-    <!-- no translation found for input_access_emoji (8105642858900406351) -->
-    <skip />
-    <!-- no translation found for input_access_voice_typing (7291201476395326141) -->
-    <skip />
+    <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"Effacer le texte"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"Raccourcis"</string>
+    <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Recherchez des raccourcis"</string>
+    <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Aucun raccourci trouvé"</string>
+    <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Système"</string>
+    <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Entrée"</string>
+    <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"Ouvrir applis"</string>
+    <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"Appli actuelle"</string>
+    <string name="group_system_access_notification_shade" msgid="7116898151485382275">"Accéder au volet de notification"</string>
+    <string name="group_system_full_screenshot" msgid="7389040853798023211">"Prendre une capture d\'écran complète"</string>
+    <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"Accéder à la liste des raccourcis du système/des applications"</string>
+    <string name="group_system_go_back" msgid="8838454003680364227">"Retour : retour à l\'état précédent (bouton précédent)"</string>
+    <string name="group_system_access_home_screen" msgid="1857344316928441909">"Accéder à l\'écran d\'accueil"</string>
+    <string name="group_system_overview_open_apps" msgid="6897128761003265350">"Aperçu des applications ouvertes"</string>
+    <string name="group_system_cycle_forward" msgid="9202444850838205990">"Parcourir les applications récentes (avancer)"</string>
+    <string name="group_system_cycle_back" msgid="5163464503638229131">"Parcourir les applications récentes (retour)"</string>
+    <string name="group_system_access_all_apps_search" msgid="488070738028991753">"Accéder à la liste des applis et à la recherche (recherche/lanceur)"</string>
+    <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"Masquer et (ré)afficher la barre des tâches"</string>
+    <string name="group_system_access_system_settings" msgid="7961639365383008053">"Accéder aux paramètres système"</string>
+    <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Accéder à l\'Assistant Google"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"Écran de verrouillage"</string>
+    <string name="group_system_quick_memo" msgid="2914234890158583919">"Ouvrir l\'application de prise de notes pour prendre des notes rapides"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"Multitâche du système"</string>
+    <string name="system_multitasking_rhs" msgid="6593269428880305699">"Passer à l\'écran partagé avec l\'application actuelle à droite"</string>
+    <string name="system_multitasking_lhs" msgid="8839380725557952846">"Passer à l\'écran partagé avec l\'application actuelle à gauche"</string>
+    <string name="system_multitasking_full_screen" msgid="1962084334200006297">"Passer de l\'écran partagé au plein écran"</string>
+    <string name="system_multitasking_replace" msgid="844285282472557186">"En mode d\'écran partagé : remplacer une application par une autre"</string>
+    <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"Entrée"</string>
+    <string name="input_switch_input_language_next" msgid="3394291576873633793">"Changer la langue d\'entrée (langue suivante)"</string>
+    <string name="input_switch_input_language_previous" msgid="8823659252918609216">"Changer la langue d\'entrée (langue précédente)"</string>
+    <string name="input_access_emoji" msgid="8105642858900406351">"Accéder aux émojis"</string>
+    <string name="input_access_voice_typing" msgid="7291201476395326141">"Accéder à l\'entrée vocale"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"Applications"</string>
     <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"Assistance"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_browser (7328131901589876868) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"Navigateur (Chrome par défaut)"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"Contacts"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_email (7480359963463803511) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"Courriel (Gmail par défaut)"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"Messages texte"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"Musique"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Agenda"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_calculator (6316043911946540137) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_applications_maps (7312554713993114342) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"Calculatrice"</string>
+    <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"Maps"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"Ne pas déranger"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"Raccourci des boutons de volume"</string>
     <string name="battery" msgid="769686279459897127">"Pile"</string>
@@ -856,12 +820,9 @@
     <string name="privacy_type_media_projection" msgid="8136723828804251547">"enregistrement d\'écran"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"Sans titre"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Veille"</string>
-    <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
-    <skip />
-    <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
-    <skip />
-    <!-- no translation found for font_scaling_larger (5476242157436806760) -->
-    <skip />
+    <string name="font_scaling_dialog_title" msgid="6273107303850248375">"Taille de police"</string>
+    <string name="font_scaling_smaller" msgid="1012032217622008232">"Rapetisser"</string>
+    <string name="font_scaling_larger" msgid="5476242157436806760">"Agrandir"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"Fenêtre d\'agrandissement"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"Commandes pour la fenêtre d\'agrandissement"</string>
     <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"Effectuer un zoom avant"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7e2bada..0e089c8 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Volet des notifications"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Réglages rapides"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Réglages rapides et volet des notifications."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Écran de verrouillage"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Écran de verrouillage du profil professionnel"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Fermer"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Paramètres écran de verrouillage"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Caméra bloquée"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Caméra et micro bloqués"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micro bloqué"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode Prioritaire activé"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant à l\'écoute"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 8ff9b06..ea532f5 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel despregable"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configuración rápida"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configuración rápida e panel despregable."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Pantalla de bloqueo."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Pantalla de bloqueo do perfil de traballo"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Pechar"</string>
@@ -1111,16 +1110,10 @@
     <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>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wifi non dispoñible"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"A cámara está bloqueada"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"A cámara e o micrófono están bloqueados"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"O micrófono está bloqueado"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"O modo de prioridade está activado"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"A atención do Asistente está activada"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index d1422ba..3f2b494 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"નોટિફિકેશન શેડ."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ઝડપી સેટિંગ."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ઝડપી સેટિંગ અને નોટિફિકેશન શેડ."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"લૉક સ્ક્રીન."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"કાર્ય લૉક સ્ક્રીન"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"બંધ કરો"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ઑફિસની પ્રોફાઇલ પર સ્વિચ કરો"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"બંધ કરો"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"લૉક સ્ક્રીનના સેટિંગ"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"વાઇ-ફાઇ ઉપલબ્ધ નથી"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"કૅમેરા બ્લૉક કરેલો છે"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"કૅમેરા અને માઇક્રોફોન બ્લૉક કરેલા છે"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"માઇક્રોફોન બ્લૉક કરેલો છે"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"પ્રાધાન્યતા મોડ ચાલુ છે"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant સક્રિય છે"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 0d08dcd..c49861b 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"त्वरित सेटिंग."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"क्विक सेटिंग और नोटिफ़िकेशन शेड."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"वर्क लॉक स्‍क्रीन"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करें"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index fadc88d..b9c6067 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Értesítési felület."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Gyorsbeállítások."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Gyorsbeállítások és értesítési terület"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lezárási képernyő."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Munka lezárási képernyővel"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Bezárás"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Lezárási képernyő beállításai"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Nem áll rendelkezésre Wi-Fi"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera letiltva"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera és mikrofon letiltva"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon letiltva"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritás mód bekapcsolva"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"A Segéd figyel"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 22877cf..018120a 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Ծանուցումների վահանակ:"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Արագ կարգավորումներ:"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Արագ կարգավորումներ և ծանուցումների վահանակ։"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Էկրանի կողպում:"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Աշխատանքային պրոֆիլի կողպէկրան"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Փակել"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Անցնել աշխատանքային պրոֆիլ"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Փակել"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Կողպէկրանի կարգավորումներ"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ցանց հասանելի չէ"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Տեսախցիկն արգելափակված է"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Տեսախցիկն ու խոսափողը արգելափակված են"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Խոսափողն արգելափակված է"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Առաջնահերթության ռեժիմը միացված է"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Օգնականը լսում է"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 262d0e1..d76d2ff 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bayangan pemberitahuan."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setelan cepat."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Setelan cepat dan Menu notifikasi."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Layar kunci."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Layar kunci kantor"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Setelan layar kunci"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi tidak tersedia"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera diblokir"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera dan mikrofon diblokir"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon diblokir"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Mode prioritas diaktifkan"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asisten sedang memerhatikan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 7bdc66c..2280524 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Tilkynningasvæði."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Flýtistillingar."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Flýtistillingar og tilkynningagluggi."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lásskjár."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vinnulásskjár"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Loka"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Skipta yfir í vinnusnið"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Loka"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Stillingar fyrir lásskjá"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi er ekki til staðar"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Lokað fyrir myndavél"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Lokað fyrir myndavél og hljóðnema"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Lokað fyrir hljóðnema"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Kveikt er á forgangsstillingu"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Hjálparinn er að hlusta"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index bc983ff..8731382 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -1110,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Impostazioni schermata di blocco"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi non disponibile"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Videocamera bloccata"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Videocamera e microfono bloccati"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Microfono bloccato"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Modalità priorità attivata"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"L\'assistente è attivo"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 859435f..8946db2 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"לוח התראות."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"הגדרות מהירות."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"הגדרות מהירות ולוח ההתראות."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"מסך נעילה."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"מסך נעילה של עבודה"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"סגירה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index ca29664..d5b96d5 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知シェード"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"クイック設定"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"クイック設定と通知シェード。"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ロック画面"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"仕事用プロファイルのロック画面"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"閉じる"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 4e40a73..54101b1 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"შეტყობინებების ფარდა"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"სწრაფი პარამეტრები"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"სწრაფი პარამეტრები და შეტყობინებების ფარდა"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ეკრანის დაბლოკვა."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"სამსახურის ჩაკეტილი ეკრანი"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"დახურვა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 459237b..dce96820 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Хабарландыру тақтасы"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Жылдам параметрлер."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Жылдам параметрлер мен хабарландыру тақтасы."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Бекіту экраны."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Әрекетті құлыптау экраны"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Жабу"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Жұмыс профиліне ауысу"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Жабу"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Экран құлпының параметрлері"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi қолжетімсіз."</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камера бөгелген."</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камера мен микрофон бөгелген."</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофон бөгелген."</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"\"Маңызды\" режимі қосулы."</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant қосулы."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index f345283..ef20217 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ពណ៌​ការ​ជូន​ដំណឹង"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ការ​កំណត់​រហ័ស។"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ការកំណត់រហ័ស និងផ្ទាំងជូនដំណឹង។"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ចាក់​សោ​អេក្រង់។"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"អេក្រង់​ចាក់​សោ​លក្ខណៈ​ការងារ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"បិទ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 6e22f36..c830e84 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ಅಧಿಸೂಚನೆಯ ಛಾಯೆ."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳು."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್‍ಗಳು ಮತ್ತು ಅಧಿಸೂಚನೆಯ ಪರದೆ."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ಲಾಕ್‌ ಸ್ಕ್ರೀನ್."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ಕೆಲಸದ ಲಾಕ್ ಪರದೆ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ಮುಚ್ಚು"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index f7a6dfb..b33168f 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"알림 세부정보"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"빠른 설정"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"빠른 설정 및 알림 창입니다."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"화면을 잠급니다."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"업무용 잠금 화면"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"닫기"</string>
@@ -616,84 +615,48 @@
     <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"알림"</string>
     <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"단축키"</string>
     <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"키보드 레이아웃 전환"</string>
-    <!-- no translation found for keyboard_shortcut_clear_text (4679927133259287577) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_title (1156178106617830429) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_hint (5982623262974326746) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_list_no_result (6819302191660875501) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_system (1151182120757052669) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_input (5440558509904296233) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_open_apps (1450959949739257562) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_search_category_current_app (2011953559133734491) -->
-    <skip />
-    <!-- no translation found for group_system_access_notification_shade (7116898151485382275) -->
-    <skip />
-    <!-- no translation found for group_system_full_screenshot (7389040853798023211) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_app_shortcuts (4421497579210445641) -->
-    <skip />
-    <!-- no translation found for group_system_go_back (8838454003680364227) -->
-    <skip />
-    <!-- no translation found for group_system_access_home_screen (1857344316928441909) -->
-    <skip />
-    <!-- no translation found for group_system_overview_open_apps (6897128761003265350) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_forward (9202444850838205990) -->
-    <skip />
-    <!-- no translation found for group_system_cycle_back (5163464503638229131) -->
-    <skip />
-    <!-- no translation found for group_system_access_all_apps_search (488070738028991753) -->
-    <skip />
-    <!-- no translation found for group_system_hide_reshow_taskbar (3809304065624351131) -->
-    <skip />
-    <!-- no translation found for group_system_access_system_settings (7961639365383008053) -->
-    <skip />
-    <!-- no translation found for group_system_access_google_assistant (1186152943161483864) -->
-    <skip />
-    <!-- no translation found for group_system_lock_screen (7391191300363416543) -->
-    <skip />
-    <!-- no translation found for group_system_quick_memo (2914234890158583919) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_system_multitasking (1065232949510862593) -->
-    <skip />
-    <!-- no translation found for system_multitasking_rhs (6593269428880305699) -->
-    <skip />
-    <!-- no translation found for system_multitasking_lhs (8839380725557952846) -->
-    <skip />
-    <!-- no translation found for system_multitasking_full_screen (1962084334200006297) -->
-    <skip />
-    <!-- no translation found for system_multitasking_replace (844285282472557186) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_input (6888282716546625610) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_next (3394291576873633793) -->
-    <skip />
-    <!-- no translation found for input_switch_input_language_previous (8823659252918609216) -->
-    <skip />
-    <!-- no translation found for input_access_emoji (8105642858900406351) -->
-    <skip />
-    <!-- no translation found for input_access_voice_typing (7291201476395326141) -->
-    <skip />
+    <string name="keyboard_shortcut_clear_text" msgid="4679927133259287577">"텍스트 삭제"</string>
+    <string name="keyboard_shortcut_search_list_title" msgid="1156178106617830429">"단축키"</string>
+    <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"단축키 검색"</string>
+    <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"단축키 없음"</string>
+    <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"시스템"</string>
+    <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"입력"</string>
+    <string name="keyboard_shortcut_search_category_open_apps" msgid="1450959949739257562">"열린 앱"</string>
+    <string name="keyboard_shortcut_search_category_current_app" msgid="2011953559133734491">"현재 앱"</string>
+    <string name="group_system_access_notification_shade" msgid="7116898151485382275">"알림 창에 액세스"</string>
+    <string name="group_system_full_screenshot" msgid="7389040853798023211">"전체 스크린샷 촬영"</string>
+    <string name="group_system_access_system_app_shortcuts" msgid="4421497579210445641">"시스템/앱 단축키 목록에 액세스"</string>
+    <string name="group_system_go_back" msgid="8838454003680364227">"뒤로: 이전 상태로 되돌아가기(뒤로 버튼)"</string>
+    <string name="group_system_access_home_screen" msgid="1857344316928441909">"홈 화면에 액세스"</string>
+    <string name="group_system_overview_open_apps" msgid="6897128761003265350">"열린 앱 개요"</string>
+    <string name="group_system_cycle_forward" msgid="9202444850838205990">"최근 앱 간 순환(앞으로)"</string>
+    <string name="group_system_cycle_back" msgid="5163464503638229131">"최근 앱 간 순환(뒤로)"</string>
+    <string name="group_system_access_all_apps_search" msgid="488070738028991753">"모든 앱 및 검색 목록(예: 검색/런처)에 액세스"</string>
+    <string name="group_system_hide_reshow_taskbar" msgid="3809304065624351131">"태스크 바 숨김 및 다시 표시"</string>
+    <string name="group_system_access_system_settings" msgid="7961639365383008053">"시스템 설정에 액세스"</string>
+    <string name="group_system_access_google_assistant" msgid="1186152943161483864">"Google 어시스턴트에 액세스"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"잠금 화면"</string>
+    <string name="group_system_quick_memo" msgid="2914234890158583919">"빠른 메모를 위해 노트 앱 불러오기"</string>
+    <string name="keyboard_shortcut_group_system_multitasking" msgid="1065232949510862593">"시스템 멀티태스킹"</string>
+    <string name="system_multitasking_rhs" msgid="6593269428880305699">"현재 앱을 오른쪽으로 보내는 화면 분할 입력"</string>
+    <string name="system_multitasking_lhs" msgid="8839380725557952846">"현재 앱을 왼쪽으로 보내는 화면 분할 입력"</string>
+    <string name="system_multitasking_full_screen" msgid="1962084334200006297">"화면 분할에서 전체 화면으로 전환"</string>
+    <string name="system_multitasking_replace" msgid="844285282472557186">"화면 분할 중: 다른 앱으로 바꾸기"</string>
+    <string name="keyboard_shortcut_group_input" msgid="6888282716546625610">"입력"</string>
+    <string name="input_switch_input_language_next" msgid="3394291576873633793">"입력 언어 전환(다음 언어)"</string>
+    <string name="input_switch_input_language_previous" msgid="8823659252918609216">"입력 언어 전환(이전 언어)"</string>
+    <string name="input_access_emoji" msgid="8105642858900406351">"이모티콘에 액세스"</string>
+    <string name="input_access_voice_typing" msgid="7291201476395326141">"음성 입력에 액세스"</string>
     <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"애플리케이션"</string>
     <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"지원"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_browser (7328131901589876868) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_browser" msgid="7328131901589876868">"브라우저(Chrome을 기본값으로 설정)"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"연락처"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_email (7480359963463803511) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_email" msgid="7480359963463803511">"이메일(Gmail을 기본값으로 설정)"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"음악"</string>
     <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"캘린더"</string>
-    <!-- no translation found for keyboard_shortcut_group_applications_calculator (6316043911946540137) -->
-    <skip />
-    <!-- no translation found for keyboard_shortcut_group_applications_maps (7312554713993114342) -->
-    <skip />
+    <string name="keyboard_shortcut_group_applications_calculator" msgid="6316043911946540137">"계산기"</string>
+    <string name="keyboard_shortcut_group_applications_maps" msgid="7312554713993114342">"지도"</string>
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"방해 금지 모드"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"볼륨 버튼 단축키"</string>
     <string name="battery" msgid="769686279459897127">"배터리"</string>
@@ -856,12 +819,9 @@
     <string name="privacy_type_media_projection" msgid="8136723828804251547">"화면 녹화"</string>
     <string name="music_controls_no_title" msgid="4166497066552290938">"제목 없음"</string>
     <string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"대기"</string>
-    <!-- no translation found for font_scaling_dialog_title (6273107303850248375) -->
-    <skip />
-    <!-- no translation found for font_scaling_smaller (1012032217622008232) -->
-    <skip />
-    <!-- no translation found for font_scaling_larger (5476242157436806760) -->
-    <skip />
+    <string name="font_scaling_dialog_title" msgid="6273107303850248375">"글꼴 크기"</string>
+    <string name="font_scaling_smaller" msgid="1012032217622008232">"축소"</string>
+    <string name="font_scaling_larger" msgid="5476242157436806760">"확대"</string>
     <string name="magnification_window_title" msgid="4863914360847258333">"확대 창"</string>
     <string name="magnification_controls_title" msgid="8421106606708891519">"확대 창 컨트롤"</string>
     <string name="accessibility_control_zoom_in" msgid="1189272315480097417">"확대"</string>
@@ -1150,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"직장 프로필로 전환"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"닫기"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"잠금 화면 설정"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi를 사용할 수 없음"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"카메라 차단됨"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"카메라 및 마이크 차단됨"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"마이크 차단됨"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"우선순위 모드 설정됨"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"어시스턴트가 대기 중임"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 3d6a949..d50e197 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Билдирмелер тактасы."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Тез тууралоолор."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ыкчам параметрлер жана билдирмелер тактасы."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Кулпуланган экран."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Жумуштун кулпуланган экраны"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Жабуу"</string>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index bc63c9f..4f38e60 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -64,5 +64,6 @@
 
     <dimen name="qs_panel_padding_top">@dimen/qqs_layout_margin_top</dimen>
 
-    <dimen name="controls_padding_horizontal">16dp</dimen>
+    <dimen name="controls_header_horizontal_padding">12dp</dimen>
+    <dimen name="controls_content_margin_horizontal">16dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 0b5b5de..4161049 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ໜ້າຈໍແຈ້ງເຕືອນ."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ການຕັ້ງຄ່າດ່ວນ."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ການຕັ້ງຄ່າດ່ວນ ແລະ ເງົາການແຈ້ງເຕືອນ."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ລັອກ​ໜ້າ​ຈໍ."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ໜ້າຈໍລັອກວຽກ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ປິດ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index d607b17..b374789 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Pranešimų gaubtas."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Spartieji nustatymai."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Spartieji nustatymai ir pranešimų skydelis."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Užrakinimo ekranas."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Darbo profilio užrakinimo ekranas"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Uždaryti"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 30ffd4b..f82bcd6 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Paziņojumu panelis"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Ātrie iestatījumi"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Ātrie iestatījumi un paziņojumu panelis."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Bloķēšanas ekrāns."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Darba profila bloķēšanas ekrāns"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Aizvērt"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Bloķēšanas ekrāna iestatījumi"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi nav pieejams"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera ir bloķēta"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kameras un mikrofona lietošana ir bloķēta"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofons ir bloķēts"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Prioritātes režīms ir ieslēgts"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asistents klausās"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index cda4a85..64631c8 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панел за известување"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Брзи поставки."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"„Брзи поставки“ и „Панел со известувања“."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заклучи екран."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Работен заклучен екран"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Затвори"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Префрли се на работен профил"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Затвори"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Поставки за заклучен екран"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi не е достапно"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камерата е блокирана"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камерата и микрофонот се блокирани"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Микрофонот е блокиран"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Приоритетниот режим е вклучен"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Вниманието на „Помошникот“ е вклучено"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 5802410..75633a2 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"അറിയിപ്പ് ഷെയ്‌ഡ്."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ദ്രുത ക്രമീകരണങ്ങൾ."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"അറിയിപ്പ് ഷെയ്‌ഡിനുള്ള ദ്രുത ക്രമീകരണം."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ലോക്ക് സ്‌ക്രീൻ."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ഔദ്യോഗിക ലോക്ക് സ്ക്രീൻ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"അവസാനിപ്പിക്കുക"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 3e6405c..c1be9f7 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Мэдэгдлийн хураангуй самбар"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Шуурхай тохиргоо."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Шуурхай тохиргоо болон мэдэгдлийн хураангуй самбар."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Дэлгэц түгжих."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ажлын түгжигдсэн дэлгэц"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Хаах"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index f582a9f..b729efc 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना शेड."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"क्विक सेटिंग्ज."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"क्विक सेटिंग्ज आणि सूचना शेड."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"लॉक स्क्रीन."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"कार्य लॉक स्क्रीन"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"बंद करा"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"कार्य प्रोफाइलवर स्विच करा"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"बंद करा"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"लॉक स्क्रीन सेटिंग्ज"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"वाय-फाय उपलब्ध नाही"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"कॅमेरा ब्लॉक केला"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"कॅमेरा आणि मायक्रोफोन ब्लॉक केले आहेत"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"मायक्रोफोन ब्लॉक केला"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"प्राधान्य मोड सुरू आहे"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant चे लक्ष हे आता अ‍ॅक्टिव्ह आहे"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 4624a4ba..9ed0636 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bidai pemberitahuan."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Tetapan pantas."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Tetapan pantas dan Bidai pemberitahuan."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kunci skrin."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrin kunci kerja"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Tutup"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 6463480..88165a8 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"အ​ကြောင်းကြားစာအကွက်"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"အမြန်လုပ် အပြင်အဆင်"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"‘အမြန်ဆက်တင်များ’ နှင့် ‘အကြောင်းကြားစာအကွက်’။"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"မျက်နှာပြင် သော့ပိတ်ရန်"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"အလုပ်သုံး လော့ခ်မျက်နှာပြင်"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ပိတ်ရန်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 94ebf2b..33d87ea 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Varselskygge."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hurtiginnstillinger."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hurtiginnstillinger og varselpanelet"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låseskjerm."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låseskjerm for arbeid"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Lukk"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d16e91f..48e134b 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"सूचना कक्ष।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"द्रुत सेटिङहरू"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"द्रुत सेटिङ तथा सूचना कक्ष।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"स्क्रीन बन्द गर्नुहोस्।"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"कार्य प्रोफाइलको लक स्क्रिन"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"बन्द गर्नुहोस्"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 995abb0..2f86231 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meldingenpaneel."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snelle instellingen."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Snelle instellingen en meldingenpaneel."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Vergrendelscherm."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Vergrendelscherm voor werk"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Sluiten"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index f1b69b4..4ac1f84 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ବିଜ୍ଞପ୍ତି ଶେଡ୍‍।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"କ୍ୱିକ୍ ସେଟିଂସ୍।"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"କୁଇକ ସେଟିଂସ ଏବଂ ବିଜ୍ଞପ୍ତି ସେଡ।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"ଲକ୍‌ ସ୍କ୍ରୀନ୍‌।"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ୱର୍କ ଲକ୍‍ ସ୍କ୍ରୀନ୍‍"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ବନ୍ଦ କରନ୍ତୁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 0c7708f..2360930 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"ਸੂਚਨਾ ਸ਼ੇਡ।"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ।"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸੂਚਨਾ ਸ਼ੇਡ।"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">" ਲਾਕ  ਸਕ੍ਰੀਨ।"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"ਕਾਰਜ-ਸਥਾਨ  ਲਾਕ  ਸਕ੍ਰੀਨ"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"ਬੰਦ ਕਰੋ"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ \'ਤੇ ਜਾਓ"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ਬੰਦ ਕਰੋ"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"ਵਾਈ-ਫਾਈ ਉਪਲਬਧ ਨਹੀਂ"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"ਕੈਮਰਾ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"ਕੈਮਰਾ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤੇ ਗਏ"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਬਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"ਤਰਜੀਹ ਮੋਡ ਚਾਲੂ ਹੈ"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Assistant ਧਿਆਨ ਸੁਵਿਧਾ ਨੂੰ ਚਾਲੂ ਹੈ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 611e996..18450ab 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Obszar powiadomień."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Szybkie ustawienia."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Szybkie ustawienia i obszar powiadomień."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ekran blokady."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekran blokady wyświetlany podczas działania"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zamknij"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Ustawienia ekranu blokady"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Sieć Wi-Fi jest niedostępna"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera jest zablokowana"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon są zablokowane"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Mikrofon jest zablokowany"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Tryb priorytetowy jest włączony"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Asystent jest aktywny"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 105031c..8add565 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Aba de notificações."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configurações rápidas."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configurações rápidas e aba de notificações."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Tela de bloqueio."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Tela de bloqueio de trabalho"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 8145483..f8a684c 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Painel de notificações."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Definições rápidas."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Definições rápidas e painel de notificações."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ecrã de bloqueio."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ecrã de bloqueio de trabalho"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 105031c..8add565 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Aba de notificações."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Configurações rápidas."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Configurações rápidas e aba de notificações."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Tela de bloqueio."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Tela de bloqueio de trabalho"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Fechar"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 0303e64..a4698d6 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Fereastră pentru notificări."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Setări rapide."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Fereastră de Setări rapide și notificări."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ecranul de blocare."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ecran de blocare pentru serviciu"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Închide"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 9a71eea..32a784c 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панель уведомлений"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Быстрые настройки"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Быстрые настройки и панель уведомлений."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Экран блокировки."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Заблокировано"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Закрыть"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index ba04fab..8bb334e 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"දැනුම්දීම් ආවරණය."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"ක්ෂණික සැකසීම්."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"ඉක්මන් සැකසීම් සහ දැනුම්දීම් ඡායිතය."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"අගුළු තිරය."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"කාර්යාල අගුලු තිරය"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"වසන්න"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 36058de..f418154 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Panel upozornení."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Rýchle nastavenia."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Rýchle nastavenia a panel upozornení"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Uzamknutá obrazovka"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Uzamknutá obrazovka pracovného profilu"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zavrieť"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index f4ae067..3bc8351 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Zaslon z obvestili."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hitre nastavitve."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hitre nastavitve in zaslon z obvestili"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Zaklenjen zaslon"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaklenjen zaslon delovnega profila"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zapri"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index f69221a..6a35e38e 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Streha e njoftimeve."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Cilësimet e shpejta."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"\"Cilësimet e shpejta\" dhe \"Streha e njoftimeve\"."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Ekrani i kyçjes."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ekrani i kyçjes së punës"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Mbylle"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 19e5952..8dcf0cd 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Meddelandepanel."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Snabbinställningar."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Snabbinställningar och meddelandepanel."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Låsskärm."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Låsskärm för arbete"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Stäng"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 1cfa514..49d4733 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Kivuli cha arifa."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mipangilio ya haraka."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Mipangilio ya haraka na Sehemu ya arifa."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Skrini iliyofungwa."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Skrini iliyofungwa ya kazini"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Funga"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Mipangilio ya skrini iliyofungwa"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi haipatikani"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera imezuiwa"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera na maikrofoni zimezuiwa"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Maikrofoni imezuiwa"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Hali ya kipaumbele imewashwa"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Programu ya Mratibu imewashwa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 7cd1470..59becc6 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -87,4 +87,7 @@
 
     <!-- Biometric Auth pattern view size, better to align keyguard_security_width -->
     <dimen name="biometric_auth_pattern_view_size">348dp</dimen>
+
+    <dimen name="controls_header_horizontal_padding">12dp</dimen>
+    <dimen name="controls_content_margin_horizontal">24dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
index 9ed9360..8583f05 100644
--- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml
@@ -37,6 +37,8 @@
     <dimen name="qs_media_rec_album_size">112dp</dimen>
     <dimen name="qs_media_rec_album_side_margin">16dp</dimen>
 
+    <dimen name="controls_panel_corner_radius">40dp</dimen>
+
     <dimen name="lockscreen_shade_max_over_scroll_amount">42dp</dimen>
 
     <!-- Roughly the same distance as media on LS to media on QS. We will translate by this value
diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
index 8b41a44..9248d58 100644
--- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml
@@ -33,5 +33,7 @@
      side -->
     <dimen name="qs_tiles_page_horizontal_margin">60dp</dimen>
 
+    <dimen name="controls_panel_corner_radius">46dp</dimen>
+
     <dimen name="notification_section_divider_height">16dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 8f59df6..2086459 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -19,7 +19,8 @@
     <!-- gap on either side of status bar notification icons -->
     <dimen name="status_bar_icon_padding">1dp</dimen>
 
-    <dimen name="controls_padding_horizontal">40dp</dimen>
+    <dimen name="controls_header_horizontal_padding">28dp</dimen>
+    <dimen name="controls_content_margin_horizontal">40dp</dimen>
 
     <dimen name="large_screen_shade_header_height">56dp</dimen>
 
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index a29df59..4a0cb46 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"నోటిఫికేషన్ షేడ్."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"శీఘ్ర సెట్టింగ్‌లు."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"క్విక్ సెట్టింగ్‌లు, నోటిఫికేషన్ తెర."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"లాక్ స్క్రీన్."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"కార్యాలయ లాక్ స్క్రీన్"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"మూసివేస్తుంది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index f0a2123..64a5280 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1110,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"สลับไปใช้โปรไฟล์งาน"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"ปิด"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"การตั้งค่าหน้าจอล็อก"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Wi-Fi ไม่พร้อมใช้งาน"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"กล้องถูกบล็อกอยู่"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"กล้องและไมโครโฟนถูกบล็อกอยู่"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"ไมโครโฟนถูกบล็อกอยู่"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"โหมดลำดับความสำคัญเปิดอยู่"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"การเรียกใช้งาน Assistant เปิดอยู่"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 05f4628..d4d583f 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Notification shade."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Mga mabilisang setting."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Mga mabilisang setting at Notification shade."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Lock screen."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Lock screen sa trabaho"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Isara"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 81f8486..4df50fc 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bildirim gölgesi."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Hızlı ayarlar."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Hızlı ayarlar ve Bildirim gölgesi."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Kilit ekranı"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"İş profili kilit ekranı"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Kapat"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 3ba43d5..c24f858 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Панель сповіщень."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Швидке налаштування."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Швидкі налаштування й панель сповіщень."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Заблокований екран."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Екран блокування завдання"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Закрити"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Перейти в робочий профіль"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Закрити"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Параметри заблокованого екрана"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Мережа Wi-Fi недоступна"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Камеру заблоковано"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Камеру й мікрофон заблоковано"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Мікрофон заблоковано"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Режим пріоритету ввімкнено"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Асистента активовано"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 5388be5..17ff36b 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"اطلاعاتی شیڈ۔"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"فوری ترتیبات۔"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"فوری ترتیبات اور اطلاعاتی شیڈ۔"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"مقفل اسکرین۔"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"دفتری مقفل اسکرین"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"بند کریں"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index d97be06..0b488f8 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Bóng thông báo."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Cài đặt nhanh."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Cài đặt nhanh và ngăn thông báo."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Màn hình khóa."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Màn hình khóa công việc"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Đóng"</string>
@@ -1111,16 +1110,10 @@
     <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>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Cài đặt màn hình khoá"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"Không có Wi-Fi"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Máy ảnh bị chặn"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Máy ảnh và micrô bị chặn"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Micrô bị chặn"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Chế độ ưu tiên đang bật"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Trợ lý đang bật"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ea1c94a..b5d0e01 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知栏。"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快捷设置。"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快捷设置和通知栏。"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"锁定屏幕。"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"工作锁定屏幕"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"关闭"</string>
@@ -1019,7 +1018,7 @@
     <string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string>
     <string name="preference_summary_default_combination" msgid="8453246369903749670">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="NETWORKMODE">%2$s</xliff:g>"</string>
     <string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string>
-    <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"暂时已连接"</string>
+    <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>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index cfd1cc8..cacf205 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知欄。"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快速設定。"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快速設定和通知欄。"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"上鎖畫面。"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"工作螢幕鎖定"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 450a3cc..3fbdd48 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"通知欄。"</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"快捷設定。"</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"快速設定和通知欄。"</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"螢幕鎖定。"</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Work 螢幕鎖定"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"關閉"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 85854c5..8039ca1 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -198,8 +198,7 @@
     <skip />
     <string name="accessibility_desc_notification_shade" msgid="5355229129428759989">"Umthunzi wesaziso."</string>
     <string name="accessibility_desc_quick_settings" msgid="4374766941484719179">"Izilingiselelo ezisheshayo."</string>
-    <!-- no translation found for accessibility_desc_qs_notification_shade (8327226953072700376) -->
-    <skip />
+    <string name="accessibility_desc_qs_notification_shade" msgid="8327226953072700376">"Amasethingi asheshayo Nomthunzi wezaziso."</string>
     <string name="accessibility_desc_lock_screen" msgid="5983125095181194887">"Khiya isikrini."</string>
     <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Ukukhiya isikrini somsebenzi"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Vala"</string>
@@ -1111,16 +1110,10 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Shintshela kuphrofayela yomsebenzi"</string>
     <string name="call_from_work_profile_close" msgid="7927067108901068098">"Vala"</string>
     <string name="lock_screen_settings" msgid="9197175446592718435">"Amasethingi okukhiya isikrini"</string>
-    <!-- no translation found for wifi_unavailable_dream_overlay_content_description (2024166212194640100) -->
-    <skip />
-    <!-- no translation found for camera_blocked_dream_overlay_content_description (4074759493559418130) -->
-    <skip />
-    <!-- no translation found for camera_and_microphone_blocked_dream_overlay_content_description (7891078093416249764) -->
-    <skip />
-    <!-- no translation found for microphone_blocked_dream_overlay_content_description (5466897982130007033) -->
-    <skip />
-    <!-- no translation found for priority_mode_dream_overlay_content_description (6044561000253314632) -->
-    <skip />
-    <!-- no translation found for assistant_attention_content_description (6830215897604642875) -->
-    <skip />
+    <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"I-Wi-Fi ayitholakali"</string>
+    <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Ikhamera ivinjiwe"</string>
+    <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Ikhamera nemakrofoni zivinjiwe"</string>
+    <string name="microphone_blocked_dream_overlay_content_description" msgid="5466897982130007033">"Imakrofoni ivinjiwe"</string>
+    <string name="priority_mode_dream_overlay_content_description" msgid="6044561000253314632">"Imodi ebalulekile ivuliwe"</string>
+    <string name="assistant_attention_content_description" msgid="6830215897604642875">"Ukunaka kwe-Assistant kuvuliwe"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ac07d564..aba3fc4 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -257,9 +257,6 @@
     <!-- Radius for notifications corners with adjacent notifications -->
     <dimen name="notification_corner_radius_small">4dp</dimen>
 
-    <!-- Vertical padding of the FSI container -->
-    <dimen name="fsi_chrome_vertical_padding">80dp</dimen>
-
     <!-- the padding of the shelf icon container -->
     <dimen name="shelf_icon_container_padding">13dp</dimen>
 
@@ -576,7 +573,7 @@
     <dimen name="qs_tile_margin_horizontal">8dp</dimen>
     <dimen name="qs_tile_margin_vertical">@dimen/qs_tile_margin_horizontal</dimen>
     <dimen name="qs_tile_margin_top_bottom">4dp</dimen>
-    <dimen name="qs_brightness_margin_top">12dp</dimen>
+    <dimen name="qs_brightness_margin_top">8dp</dimen>
     <dimen name="qs_brightness_margin_bottom">16dp</dimen>
     <dimen name="qqs_layout_margin_top">16dp</dimen>
     <dimen name="qqs_layout_padding_bottom">24dp</dimen>
@@ -628,7 +625,7 @@
     <dimen name="qs_header_row_min_height">48dp</dimen>
 
     <dimen name="qs_header_non_clickable_element_height">24dp</dimen>
-    <dimen name="new_qs_header_non_clickable_element_height">20dp</dimen>
+    <dimen name="new_qs_header_non_clickable_element_height">24dp</dimen>
 
     <dimen name="qs_footer_padding">20dp</dimen>
     <dimen name="qs_security_footer_height">88dp</dimen>
@@ -1195,11 +1192,13 @@
 
     <!-- Home Controls -->
     <dimen name="controls_header_menu_size">48dp</dimen>
+    <dimen name="controls_header_menu_button_size">48dp</dimen>
     <dimen name="controls_header_bottom_margin">16dp</dimen>
+    <dimen name="controls_header_horizontal_padding">12dp</dimen>
     <dimen name="controls_header_app_icon_size">24dp</dimen>
     <dimen name="controls_top_margin">48dp</dimen>
-    <dimen name="controls_padding_horizontal">0dp</dimen>
-    <dimen name="control_header_text_size">20sp</dimen>
+    <dimen name="controls_content_margin_horizontal">0dp</dimen>
+    <dimen name="control_header_text_size">24sp</dimen>
     <dimen name="control_item_text_size">16sp</dimen>
     <dimen name="control_menu_item_text_size">16sp</dimen>
     <dimen name="control_menu_item_min_height">56dp</dimen>
@@ -1230,6 +1229,8 @@
     <item name="controls_task_view_width_percentage" translatable="false" format="float" type="dimen">1.0</item>
     <dimen name="controls_task_view_right_margin">0dp</dimen>
 
+    <dimen name="controls_panel_corner_radius">42dp</dimen>
+
     <!-- Home Controls activity view detail panel-->
     <dimen name="controls_activity_view_corner_radius">@*android:dimen/config_bottomDialogCornerRadius</dimen>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7b3caff..a988813 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -407,8 +407,12 @@
 
     <!-- Message shown when the system-provided fingerprint dialog is shown, asking for authentication -->
     <string name="fingerprint_dialog_touch_sensor">Touch the fingerprint sensor</string>
-    <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
-    <string name="accessibility_fingerprint_dialog_fingerprint_icon">Fingerprint icon</string>
+    <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (tablet) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.\n\nPressing the power button turns off the screen.</string>
+    <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (device) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="device">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the device.\n\nPressing the power button turns off the screen.</string>
+    <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (default) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
+    <string name="security_settings_sfps_enroll_find_sensor_message" product="default">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the phone.\n\nPressing the power button turns off the screen.</string>
     <!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
     <string name="fingerprint_dialog_use_fingerprint_instead">Can\u2019t recognize face. Use fingerprint instead.</string>
     <!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
@@ -2431,6 +2435,10 @@
          panel (embedded activity) instead of controls rendered by SystemUI [CHAR LIMIT=NONE] -->
     <string name="controls_panel_authorization">When you add <xliff:g id="appName" example="My app">%s</xliff:g>, it can add controls and content to this panel. In some apps, you can choose which controls show up here.</string>
 
+    <!-- Shows in a dialog presented to the user to authorize this app removal from a Device
+         controls panel [CHAR LIMIT=NONE] -->
+    <string name="controls_panel_remove_app_authorization">Remove controls for <xliff:g example="My app" id="appName">%s</xliff:g>?</string>
+
     <!-- a11y state description for a control that is currently favorited [CHAR LIMIT=NONE] -->
     <string name="accessibility_control_favorite">Favorited</string>
     <!-- a11y state description for a control that is currently favorited with its position [CHAR LIMIT=NONE] -->
@@ -2471,6 +2479,8 @@
     <string name="controls_dialog_title">Add to device controls</string>
     <!-- Controls dialog add to favorites [CHAR LIMIT=40] -->
     <string name="controls_dialog_ok">Add</string>
+    <!-- Controls dialog remove app from a panel [CHAR LIMIT=40] -->
+    <string name="controls_dialog_remove">Remove</string>
     <!-- Controls dialog message. Indicates app that suggested this control [CHAR LIMIT=NONE] -->
     <string name="controls_dialog_message">Suggested by <xliff:g id="app" example="System UI">%s</xliff:g></string>
     <!-- Controls tile secondary label when device is locked and user does not want access to controls from lockscreen [CHAR LIMIT=20] -->
@@ -2588,6 +2598,8 @@
     <string name="controls_menu_edit">Edit controls</string>
     <!-- Controls menu, add another app [CHAR LIMIT=30] -->
     <string name="controls_menu_add_another_app">Add app</string>
+    <!-- Controls menu, remove app [CHAR_LIMIT=30] -->
+    <string name="controls_menu_remove">Remove app</string>
 
     <!-- Title for the media output dialog with media related devices [CHAR LIMIT=50] -->
     <string name="media_output_dialog_add_output">Add outputs</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
index 12e0b9a..c5979cc 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimator.kt
@@ -65,35 +65,40 @@
             } else {
                 1
             }
-        viewsToTranslate.forEach { (view, direction, shouldBeAnimated) ->
-            if (shouldBeAnimated()) {
-                view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
-            }
+        viewsToTranslate.forEach { (view, direction) ->
+            view.get()?.translationX = xTrans * direction.multiplier * rtlMultiplier
         }
     }
 
     /** Finds in [parent] all views specified by [ids] and register them for the animation. */
     private fun registerViewsForAnimation(parent: ViewGroup, ids: Set<ViewIdToTranslate>) {
         viewsToTranslate =
-            ids.mapNotNull { (id, dir, pred) ->
-                parent.findViewById<View>(id)?.let { view ->
-                    ViewToTranslate(WeakReference(view), dir, pred)
+            ids.asSequence()
+                .filter { it.shouldBeAnimated() }
+                .mapNotNull {
+                    parent.findViewById<View>(it.viewId)?.let { view ->
+                        ViewToTranslate(WeakReference(view), it.direction)
+                    }
                 }
-            }
+                .toList()
     }
 
-    /** Represents a view to animate. [rootView] should contain a view with [viewId] inside. */
+    /**
+     * Represents a view to animate. [rootView] should contain a view with [viewId] inside.
+     * [shouldBeAnimated] is only evaluated when the viewsToTranslate is registered in
+     * [registerViewsForAnimation].
+     */
     data class ViewIdToTranslate(
         val viewId: Int,
         val direction: Direction,
         val shouldBeAnimated: () -> Boolean = { true }
     )
 
-    private data class ViewToTranslate(
-        val view: WeakReference<View>,
-        val direction: Direction,
-        val shouldBeAnimated: () -> Boolean
-    )
+    /**
+     * Represents a view whose animation process is in-progress. It should be immutable because the
+     * started animation should be completed.
+     */
+    private data class ViewToTranslate(val view: WeakReference<View>, val direction: Direction)
 
     /** Direction of the animation. */
     enum class Direction(val multiplier: Float) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
index 23742c5..454294f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
@@ -87,7 +87,7 @@
      * Helper for evaluating 3-valued logical AND/OR.
      *
      * @param returnValueIfAnyMatches AND returns false if any value is false. OR returns true if
-     * any value is true.
+     *   any value is true.
      */
     private fun threeValuedAndOrOr(
         conditions: Collection<Condition>,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
index b927155..8690b36 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/PreviewPositionHelper.java
@@ -62,7 +62,7 @@
      */
     public void updateThumbnailMatrix(Rect thumbnailBounds, ThumbnailData thumbnailData,
             int canvasWidth, int canvasHeight, int screenWidthPx, int screenHeightPx,
-            int taskbarSize, boolean isTablet,
+            int taskbarSize, boolean isLargeScreen,
             int currentRotation, boolean isRtl) {
         boolean isRotated = false;
         boolean isOrientationDifferent;
@@ -95,7 +95,7 @@
             canvasScreenRatio = (float) canvasWidth / screenWidthPx;
         }
         scaledTaskbarSize = taskbarSize * canvasScreenRatio;
-        thumbnailClipHint.bottom = isTablet ? scaledTaskbarSize : 0;
+        thumbnailClipHint.bottom = isLargeScreen ? scaledTaskbarSize : 0;
 
         float scale = thumbnailData.scale;
         final float thumbnailScale;
@@ -103,7 +103,7 @@
         // Landscape vs portrait change.
         // Note: Disable rotation in grid layout.
         boolean windowingModeSupportsRotation =
-                thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN && !isTablet;
+                thumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN && !isLargeScreen;
         isOrientationDifferent = isOrientationChange(deltaRotate)
                 && windowingModeSupportsRotation;
         if (canvasWidth == 0 || canvasHeight == 0 || scale == 0) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
index 77a13bd..751a3f8 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
@@ -137,7 +137,7 @@
 
     /** @return whether or not {@param context} represents that of a large screen device or not */
     @TargetApi(Build.VERSION_CODES.R)
-    public static boolean isTablet(Context context) {
+    public static boolean isLargeScreen(Context context) {
         final WindowManager windowManager = context.getSystemService(WindowManager.class);
         final Rect bounds = windowManager.getCurrentWindowMetrics().getBounds();
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index 7d39c4a..dd60647 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -23,6 +23,7 @@
 import android.annotation.IntDef;
 import android.content.Context;
 import android.content.res.Resources;
+import android.os.SystemProperties;
 import android.view.ViewConfiguration;
 import android.view.WindowManagerPolicyConstants;
 
@@ -115,6 +116,9 @@
     public static final int SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE = 1 << 26;
     // Device dreaming state
     public static final int SYSUI_STATE_DEVICE_DREAMING = 1 << 27;
+    // Whether the back gesture is allowed (or ignored) by the Shade
+    public static final boolean ALLOW_BACK_GESTURE_IN_SHADE = SystemProperties.getBoolean(
+            "persist.wm.debug.shade_allow_back_gesture", false);
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SYSUI_STATE_SCREEN_PINNING,
@@ -243,9 +247,14 @@
             sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
         }
         // Disable when in immersive, or the notifications are interactive
-        int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN
-                | SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
-                | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
+        int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
+
+        // EdgeBackGestureHandler ignores Back gesture when SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED.
+        // To allow Shade to respond to Back, we're bypassing this check (behind a flag).
+        if (!ALLOW_BACK_GESTURE_IN_SHADE) {
+            disableFlags |= SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
+        }
+
         return (sysuiStateFlags & disableFlags) != 0;
     }
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 90f44a7..ae68618 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -22,10 +22,7 @@
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
 import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
-import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
 import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
 import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
@@ -46,6 +43,8 @@
 import android.window.TransitionInfo;
 import android.window.TransitionInfo.Change;
 
+import com.android.wm.shell.util.TransitionUtil;
+
 import java.util.ArrayList;
 import java.util.function.Predicate;
 
@@ -75,7 +74,7 @@
     private static void setupLeash(@NonNull SurfaceControl leash,
             @NonNull TransitionInfo.Change change, int layer,
             @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
-        boolean isOpening = info.getType() == TRANSIT_OPEN || info.getType() == TRANSIT_TO_FRONT;
+        final boolean isOpening = TransitionUtil.isOpeningType(info.getType());
         // Put animating stuff above this line and put static stuff below it.
         int zSplitLine = info.getChanges().size();
         // changes should be ordered top-to-bottom in z
@@ -88,7 +87,7 @@
                 absBounds.top - info.getRootOffset().y);
 
         // Put all the OPEN/SHOW on top
-        if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) {
+        if (TransitionUtil.isOpeningType(mode)) {
             if (isOpening) {
                 t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
                 if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
@@ -99,7 +98,7 @@
                 // put on bottom and leave it visible
                 t.setLayer(leash, zSplitLine - layer);
             }
-        } else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
+        } else if (TransitionUtil.isClosingType(mode)) {
             if (isOpening) {
                 // put on bottom and leave visible
                 t.setLayer(leash, zSplitLine - layer);
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 80b9758..70a36ce 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
@@ -19,11 +19,7 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
-import static android.view.WindowManager.TRANSIT_OPEN;
-import static android.view.WindowManager.TRANSIT_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.newTarget;
 
@@ -50,6 +46,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.wm.shell.util.TransitionUtil;
 
 import java.util.ArrayList;
 
@@ -183,7 +180,7 @@
                     final RemoteAnimationTarget target = newTarget(change,
                             info.getChanges().size() - i, info, t, mLeashMap);
                     apps.add(target);
-                    if (change.getMode() == TRANSIT_CLOSE || change.getMode() == TRANSIT_TO_BACK) {
+                    if (TransitionUtil.isClosingType(change.getMode())) {
                         // raise closing (pausing) task to "above" layer so it isn't covered
                         t.setLayer(target.leash, info.getChanges().size() * 3 - i);
                         mPausingTasks.add(new TaskState(change, target.leash));
@@ -200,8 +197,7 @@
                     } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                         mRecentsTask = taskInfo.token;
                         mRecentsTaskId = taskInfo.taskId;
-                    } else if (change.getMode() == TRANSIT_OPEN
-                            || change.getMode() == TRANSIT_TO_FRONT) {
+                    } else if (TransitionUtil.isOpeningType(change.getMode())) {
                         mOpeningTasks.add(new TaskState(change, target.leash));
                     }
                 }
@@ -227,7 +223,7 @@
                 final TransitionInfo.Change change = info.getChanges().get(i);
                 final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                 final boolean isLeafTask = leafTaskFilter.test(change);
-                if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) {
+                if (TransitionUtil.isOpeningType(change.getMode())) {
                     if (mRecentsTask.equals(change.getContainer())) {
                         recentsOpening = change;
                     } else if (isLeafTask) {
@@ -240,8 +236,7 @@
                         }
                         openingTasks.add(change);
                     }
-                } else if (change.getMode() == TRANSIT_CLOSE
-                        || change.getMode() == TRANSIT_TO_BACK) {
+                } else if (TransitionUtil.isClosingType(change.getMode())) {
                     if (mRecentsTask.equals(change.getContainer())) {
                         foundRecentsClosing = true;
                     } else if (isLeafTask) {
diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
index e0cf7b6..d8085b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+++ b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
@@ -132,6 +132,7 @@
 
 /**
  * UiEvents that are logged to identify why face auth is being triggered.
+ *
  * @param extraInfo is logged as the position. See [UiEventLogger#logWithInstanceIdAndPosition]
  */
 enum class FaceAuthUiEvent
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index baaef19..f8cb38d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -44,7 +44,7 @@
 public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKeyInputView>
         extends KeyguardInputViewController<T> {
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    private final LockPatternUtils mLockPatternUtils;
+    protected final LockPatternUtils mLockPatternUtils;
     private final LatencyTracker mLatencyTracker;
     private final FalsingCollector mFalsingCollector;
     private final EmergencyButtonController mEmergencyButtonController;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
index d221e22..a010c9a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordViewController.java
@@ -26,6 +26,7 @@
 import android.view.KeyEvent;
 import android.view.View;
 import android.view.ViewGroup.MarginLayoutParams;
+import android.view.WindowInsets;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -156,6 +157,15 @@
         // TODO: Remove this workaround by ensuring such a race condition never happens.
         mMainExecutor.executeDelayed(
                 this::updateSwitchImeButton, DELAY_MILLIS_TO_REEVALUATE_IME_SWITCH_ICON);
+        mView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
+            @Override
+            public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
+                if (!mKeyguardViewController.isBouncerShowing()) {
+                    mView.hideKeyboard();
+                }
+                return insets;
+            }
+        });
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
index 92e3641..559db76 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java
@@ -71,13 +71,17 @@
     protected void onViewAttached() {
         super.onViewAttached();
 
-        for (NumPadKey button: mView.getButtons()) {
+        boolean showAnimations = !mLockPatternUtils
+                .isPinEnhancedPrivacyEnabled(KeyguardUpdateMonitor.getCurrentUser());
+        mPasswordEntry.setShowPassword(showAnimations);
+        for (NumPadKey button : mView.getButtons()) {
             button.setOnTouchListener((v, event) -> {
                 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
                     mFalsingCollector.avoidGesture();
                 }
                 return false;
             });
+            button.setAnimationEnabled(showAnimations);
         }
         mPasswordEntry.setOnKeyListener(mOnKeyListener);
         mPasswordEntry.setUserActivityListener(this::onUserInput);
@@ -102,12 +106,9 @@
         View okButton = mView.findViewById(R.id.key_enter);
         if (okButton != null) {
             okButton.setOnTouchListener(mActionButtonTouchListener);
-            okButton.setOnClickListener(new View.OnClickListener() {
-                @Override
-                public void onClick(View v) {
-                    if (mPasswordEntry.isEnabled()) {
-                        verifyPasswordAndUnlock();
-                    }
+            okButton.setOnClickListener(v -> {
+                if (mPasswordEntry.isEnabled()) {
+                    verifyPasswordAndUnlock();
                 }
             });
             okButton.setOnHoverListener(mLiftToActivateListener);
@@ -118,7 +119,7 @@
     protected void onViewDetached() {
         super.onViewDetached();
 
-        for (NumPadKey button: mView.getButtons()) {
+        for (NumPadKey button : mView.getButtons()) {
             button.setOnTouchListener(null);
         }
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index f164e7d..c6f0eee 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -39,7 +39,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.Activity;
@@ -1044,13 +1043,10 @@
 
             int yTranslation = mResources.getDimensionPixelSize(R.dimen.disappear_y_translation);
 
-            AnimatorSet anims = new AnimatorSet();
             ObjectAnimator yAnim = ObjectAnimator.ofFloat(mView, View.TRANSLATION_Y, yTranslation);
-            ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mView, View.ALPHA, 0f);
-
-            anims.setInterpolator(Interpolators.STANDARD_ACCELERATE);
-            anims.playTogether(alphaAnim, yAnim);
-            anims.start();
+            yAnim.setInterpolator(Interpolators.STANDARD_ACCELERATE);
+            yAnim.setDuration(500);
+            yAnim.start();
         }
 
         private void setupUserSwitcher() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index f1abdc6..06258b2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -637,12 +637,17 @@
 
     public void startAppearAnimation() {
         if (mCurrentSecurityMode != SecurityMode.None) {
-            mView.setAlpha(1f);
+            setAlpha(1f);
             mView.startAppearAnimation(mCurrentSecurityMode);
             getCurrentSecurityController().startAppearAnimation();
         }
     }
 
+    /** Set the alpha of the security container view */
+    public void setAlpha(float alpha) {
+        mView.setAlpha(alpha);
+    }
+
     public boolean startDisappearAnimation(Runnable onFinishRunnable) {
         boolean didRunAnimation = false;
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index b53b868..f4c5815 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -21,8 +21,6 @@
 
 import com.android.keyguard.KeyguardClockSwitch.ClockSize;
 import com.android.keyguard.logging.KeyguardLogger;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.ClockAnimations;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
@@ -62,7 +60,6 @@
             KeyguardUpdateMonitor keyguardUpdateMonitor,
             ConfigurationController configurationController,
             DozeParameters dozeParameters,
-            FeatureFlags featureFlags,
             ScreenOffAnimationController screenOffAnimationController,
             KeyguardLogger logger) {
         super(keyguardStatusView);
@@ -73,8 +70,6 @@
         mKeyguardVisibilityHelper = new KeyguardVisibilityHelper(mView, keyguardStateController,
                 dozeParameters, screenOffAnimationController, /* animateYPos= */ true,
                 logger.getBuffer());
-        mKeyguardVisibilityHelper.setOcclusionTransitionFlagEnabled(
-                featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index eb4b05b..a4ec8e1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -29,6 +29,7 @@
 import static android.hardware.biometrics.BiometricSourceType.FACE;
 import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
 import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
+import static android.os.PowerManager.WAKE_REASON_UNKNOWN;
 
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
@@ -73,11 +74,9 @@
 import android.annotation.AnyThread;
 import android.annotation.MainThread;
 import android.annotation.SuppressLint;
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.ActivityTaskManager.RootTaskInfo;
 import android.app.AlarmManager;
-import android.app.UserSwitchObserver;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
@@ -108,7 +107,6 @@
 import android.nfc.NfcAdapter;
 import android.os.CancellationSignal;
 import android.os.Handler;
-import android.os.IRemoteCallback;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
@@ -139,9 +137,9 @@
 import com.android.internal.util.LatencyTracker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.logging.KeyguardUpdateMonitorLogger;
+import com.android.settingslib.Utils;
 import com.android.settingslib.WirelessUtils;
 import com.android.settingslib.fuelgauge.BatteryStatus;
-import com.android.settingslib.Utils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.biometrics.AuthController;
@@ -152,6 +150,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.dump.DumpsysTableLogger;
+import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.plugins.WeatherData;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -180,6 +179,7 @@
 import java.util.Optional;
 import java.util.Set;
 import java.util.TimeZone;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.stream.Collectors;
 
@@ -823,6 +823,19 @@
         }
     }
 
+    private void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) {
+        Assert.isMainThread();
+        Trace.beginSection("KeyGuardUpdateMonitor#onBiometricDetected");
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onBiometricDetected(userId, biometricSourceType, isStrongBiometric);
+            }
+        }
+        Trace.endSection();
+    }
+
     @VisibleForTesting
     protected void onFingerprintAuthenticated(int userId, boolean isStrongBiometric) {
         Assert.isMainThread();
@@ -899,6 +912,20 @@
         }
     }
 
+    private void handleBiometricDetected(int authUserId, BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) {
+        Trace.beginSection("KeyGuardUpdateMonitor#handlerBiometricDetected");
+        onBiometricDetected(authUserId, biometricSourceType, isStrongBiometric);
+        if (biometricSourceType == FINGERPRINT) {
+            mLogger.logFingerprintDetected(authUserId, isStrongBiometric);
+        } else if (biometricSourceType == FACE) {
+            mLogger.logFaceDetected(authUserId, isStrongBiometric);
+            setFaceRunningState(BIOMETRIC_STATE_STOPPED);
+        }
+
+        Trace.endSection();
+    }
+
     private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
         Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
         if (mHandler.hasCallbacks(mFpCancelNotReceived)) {
@@ -950,8 +977,14 @@
 
     private void onFingerprintCancelNotReceived() {
         mLogger.e("Fp cancellation not received, transitioning to STOPPED");
+        final boolean wasCancellingRestarting = mFingerprintRunningState
+                == BIOMETRIC_STATE_CANCELLING_RESTARTING;
         mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
-        KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
+        if (wasCancellingRestarting) {
+            KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
+        } else {
+            KeyguardUpdateMonitor.this.updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
+        }
     }
 
     private void handleFingerprintError(int msgId, String errString) {
@@ -1038,6 +1071,12 @@
                     () -> updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE),
                     getBiometricLockoutDelay());
         } else {
+            boolean temporaryLockoutReset = wasLockout && !mFingerprintLockedOut;
+            if (temporaryLockoutReset) {
+                mLogger.d("temporaryLockoutReset - stopListeningForFingerprint() to stop"
+                        + " detectFingerprint");
+                stopListeningForFingerprint();
+            }
             updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
         }
 
@@ -1747,10 +1786,16 @@
                 }
             };
 
+    private final FingerprintManager.FingerprintDetectionCallback mFingerprintDetectionCallback =
+            (sensorId, userId, isStrongBiometric) -> {
+                // Trigger the fingerprint detected path so the bouncer can be shown
+                handleBiometricDetected(userId, FINGERPRINT, isStrongBiometric);
+            };
+
     private final FaceManager.FaceDetectionCallback mFaceDetectionCallback
             = (sensorId, userId, isStrongBiometric) -> {
-                // Trigger the face success path so the bouncer can be shown
-                handleFaceAuthenticated(userId, isStrongBiometric);
+                // Trigger the face detected path so the bouncer can be shown
+                handleBiometricDetected(userId, FACE, isStrongBiometric);
             };
 
     @VisibleForTesting
@@ -2175,7 +2220,7 @@
                         handleDevicePolicyManagerStateChanged(msg.arg1);
                         break;
                     case MSG_USER_SWITCHING:
-                        handleUserSwitching(msg.arg1, (IRemoteCallback) msg.obj);
+                        handleUserSwitching(msg.arg1, (CountDownLatch) msg.obj);
                         break;
                     case MSG_USER_SWITCH_COMPLETE:
                         handleUserSwitchComplete(msg.arg1);
@@ -2301,11 +2346,7 @@
                 mHandler, UserHandle.ALL);
 
         mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
-        try {
-            ActivityManager.getService().registerUserSwitchObserver(mUserSwitchObserver, TAG);
-        } catch (RemoteException e) {
-            e.rethrowAsRuntimeException();
-        }
+        mUserTracker.addCallback(mUserChangedCallback, mainExecutor);
 
         mTrustManager.registerTrustListener(this);
 
@@ -2441,17 +2482,17 @@
         return mIsFaceEnrolled;
     }
 
-    private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() {
+    private final UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() {
         @Override
-        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
+        public void onUserChanging(int newUser, Context userContext, CountDownLatch latch) {
             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHING,
-                    newUserId, 0, reply));
+                    newUser, 0, latch));
         }
 
         @Override
-        public void onUserSwitchComplete(int newUserId) {
+        public void onUserChanged(int newUser, Context userContext) {
             mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCH_COMPLETE,
-                    newUserId, 0));
+                    newUser, 0));
         }
     };
 
@@ -2783,8 +2824,7 @@
 
         boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
                 && shouldListenBouncerState && shouldListenUdfpsState
-                && shouldListenSideFpsState
-                && !isFingerprintLockedOut();
+                && shouldListenSideFpsState;
         logListenerModelData(
                 new KeyguardFingerprintListenModel(
                     System.currentTimeMillis(),
@@ -2939,11 +2979,7 @@
                 mLogger.v("startListeningForFingerprint - detect");
                 mFpm.detectFingerprint(
                         mFingerprintCancelSignal,
-                        (sensorId, user, isStrongBiometric) -> {
-                            mLogger.d("fingerprint detected");
-                            // Trigger the fingerprint success path so the bouncer can be shown
-                            handleFingerprintAuthenticated(user, isStrongBiometric);
-                        },
+                        mFingerprintDetectionCallback,
                         new FingerprintAuthenticateOptions.Builder()
                                 .setUserId(userId)
                                 .build());
@@ -2983,6 +3019,14 @@
         if (unlockPossible) {
             mFaceCancelSignal = new CancellationSignal();
 
+            final FaceAuthenticateOptions faceAuthenticateOptions =
+                    new SysUiFaceAuthenticateOptions(
+                            userId,
+                            faceAuthUiEvent,
+                            faceAuthUiEvent == FACE_AUTH_UPDATED_STARTED_WAKING_UP
+                                    ? faceAuthUiEvent.getExtraInfo()
+                                    : WAKE_REASON_UNKNOWN
+                    ).toFaceAuthenticateOptions();
             // This would need to be updated for multi-sensor devices
             final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
                     && mFaceSensorProperties.get(0).supportsFaceDetection;
@@ -2993,9 +3037,7 @@
                     // Run face detection. (If a face is detected, show the bouncer.)
                     mLogger.v("startListeningForFace - detect");
                     mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback,
-                            new FaceAuthenticateOptions.Builder()
-                                    .setUserId(userId)
-                                    .build());
+                            faceAuthenticateOptions);
                 } else {
                     // Don't run face detection. Instead, inform the user
                     // face auth is unavailable and how to proceed.
@@ -3014,7 +3056,8 @@
                 final boolean isBypassEnabled = mKeyguardBypassController != null
                         && mKeyguardBypassController.isBypassEnabled();
                 mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal,
-                        mFaceAuthenticationCallback, null /* handler */, userId);
+                        mFaceAuthenticationCallback, null /* handler */,
+                        faceAuthenticateOptions);
             }
             setFaceRunningState(BIOMETRIC_STATE_RUNNING);
         }
@@ -3175,7 +3218,7 @@
      * Handle {@link #MSG_USER_SWITCHING}
      */
     @VisibleForTesting
-    void handleUserSwitching(int userId, IRemoteCallback reply) {
+    void handleUserSwitching(int userId, CountDownLatch latch) {
         Assert.isMainThread();
         clearBiometricRecognized();
         mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
@@ -3185,11 +3228,7 @@
                 cb.onUserSwitching(userId);
             }
         }
-        try {
-            reply.sendResult(null);
-        } catch (RemoteException e) {
-            mLogger.logException(e, "Ignored exception while userSwitching");
-        }
+        latch.countDown();
     }
 
     /**
@@ -3962,13 +4001,7 @@
             mContext.getContentResolver().unregisterContentObserver(mTimeFormatChangeObserver);
         }
 
-        try {
-            ActivityManager.getService().unregisterUserSwitchObserver(mUserSwitchObserver);
-        } catch (RemoteException e) {
-            mLogger.logException(
-                    e,
-                    "RemoteException onDestroy. cannot unregister userSwitchObserver");
-        }
+        mUserTracker.removeCallback(mUserChangedCallback);
 
         TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 38f3e50..0d4889a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -214,7 +214,7 @@
     public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) { }
 
     /**
-     * Called when a biometric is recognized.
+     * Called when a biometric is authenticated.
      * @param userId the user id for which the biometric sample was authenticated
      * @param biometricSourceType
      */
@@ -222,6 +222,14 @@
             boolean isStrongBiometric) { }
 
     /**
+     * Called when a biometric is detected but not successfully authenticated.
+     * @param userId the user id for which the biometric sample was detected
+     * @param biometricSourceType
+     */
+    public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) { }
+
+    /**
      * Called when biometric authentication provides help string (e.g. "Try again")
      * @param msgId
      * @param helpString
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index 7e48193..a678edc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -28,7 +28,6 @@
 import com.android.systemui.statusbar.notification.AnimatableProperty;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -49,7 +48,6 @@
     private boolean mAnimateYPos;
     private boolean mKeyguardViewVisibilityAnimating;
     private boolean mLastOccludedState = false;
-    private boolean mIsUnoccludeTransitionFlagEnabled = false;
     private final AnimationProperties mAnimationProperties = new AnimationProperties();
     private final LogBuffer mLogBuffer;
 
@@ -77,10 +75,6 @@
         return mKeyguardViewVisibilityAnimating;
     }
 
-    public void setOcclusionTransitionFlagEnabled(boolean enabled) {
-        mIsUnoccludeTransitionFlagEnabled = enabled;
-    }
-
     /**
      * Set the visibility of a keyguard view based on some new state.
      */
@@ -156,24 +150,9 @@
                 // since it may need to be cancelled due to keyguard lifecycle events.
                 mScreenOffAnimationController.animateInKeyguard(
                         mView, mAnimateKeyguardStatusViewVisibleEndRunnable);
-            } else if (!mIsUnoccludeTransitionFlagEnabled && mLastOccludedState && !isOccluded) {
-                // An activity was displayed over the lock screen, and has now gone away
-                log("Unoccluded transition");
-                mView.setVisibility(View.VISIBLE);
-                mView.setAlpha(0f);
-
-                mView.animate()
-                        .setDuration(StackStateAnimator.ANIMATION_DURATION_WAKEUP)
-                        .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
-                        .alpha(1f)
-                        .withEndAction(mAnimateKeyguardStatusViewVisibleEndRunnable)
-                        .start();
             } else {
                 log("Direct set Visibility to VISIBLE");
                 mView.setVisibility(View.VISIBLE);
-                if (!mIsUnoccludeTransitionFlagEnabled) {
-                    mView.setAlpha(1f);
-                }
             }
         } else {
             log("Direct set Visibility to GONE");
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
index b30a0e0..ad66909 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java
@@ -51,7 +51,6 @@
     private float mStartRadius;
     private float mEndRadius;
     private int mHeight;
-    private boolean mInitialized;
 
     private static final int EXPAND_ANIMATION_MS = 100;
     private static final int EXPAND_COLOR_ANIMATION_MS = 50;
@@ -93,15 +92,15 @@
     }
 
     void onLayout(int height) {
+        boolean shouldUpdateHeight = height != mHeight;
         mHeight = height;
         mStartRadius = height / 2f;
         mEndRadius = height / 4f;
         mExpandAnimator.setFloatValues(mStartRadius, mEndRadius);
         mContractAnimator.setFloatValues(mEndRadius, mStartRadius);
         // Set initial corner radius.
-        if (!mInitialized) {
+        if (shouldUpdateHeight) {
             mBackground.setCornerRadius(mStartRadius);
-            mInitialized = true;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
index 3b0644e..7c7680a 100644
--- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
+++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java
@@ -50,6 +50,7 @@
     private int mDigit = -1;
     private int mTextViewResId;
     private PasswordTextView mTextView;
+    private boolean mAnimationsEnabled = true;
 
     @Nullable
     private NumPadAnimator mAnimator;
@@ -164,11 +165,11 @@
         switch(event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
                 doHapticKeyClick();
-                if (mAnimator != null) mAnimator.expand();
+                if (mAnimator != null && mAnimationsEnabled) mAnimator.expand();
                 break;
             case MotionEvent.ACTION_UP:
             case MotionEvent.ACTION_CANCEL:
-                if (mAnimator != null) mAnimator.contract();
+                if (mAnimator != null && mAnimationsEnabled) mAnimator.contract();
                 break;
         }
         return super.onTouchEvent(event);
@@ -228,4 +229,11 @@
             mAnimator.setProgress(progress);
         }
     }
+
+    /**
+     * Controls the animation when a key is pressed
+     */
+    public void setAnimationEnabled(boolean enabled) {
+        mAnimationsEnabled = enabled;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
index 8554e11..5400011 100644
--- a/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java
@@ -30,7 +30,6 @@
 import android.graphics.Typeface;
 import android.os.PowerManager;
 import android.os.SystemClock;
-import android.provider.Settings;
 import android.text.InputType;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -100,7 +99,7 @@
     private Interpolator mAppearInterpolator;
     private Interpolator mDisappearInterpolator;
     private Interpolator mFastOutSlowInInterpolator;
-    private boolean mShowPassword;
+    private boolean mShowPassword = true;
     private UserActivityListener mUserActivityListener;
     private PinShapeInput mPinShapeInput;
     private boolean mUsePinShapes = false;
@@ -158,8 +157,6 @@
         mDrawPaint.setTypeface(Typeface.create(
                 context.getString(com.android.internal.R.string.config_headlineFontFamily),
                 0));
-        mShowPassword = Settings.System.getInt(mContext.getContentResolver(),
-                Settings.System.TEXT_SHOW_PASSWORD, 1) == 1;
         mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
                 android.R.interpolator.linear_out_slow_in);
         mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
@@ -441,6 +438,13 @@
         addView(mPinShapeInput.getView());
     }
 
+    /**
+     * Controls whether the last entered digit is briefly shown after being entered
+     */
+    public void setShowPassword(boolean enabled) {
+        mShowPassword = enabled;
+    }
+
     private class CharState {
         char whichChar;
         ValueAnimator textAnimator;
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index c414c08..e53f6ad 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -167,6 +167,20 @@
         }, {"Fingerprint auth successful: userId: $int1, isStrongBiometric: $bool1"})
     }
 
+    fun logFaceDetected(userId: Int, isStrongBiometric: Boolean) {
+        logBuffer.log(TAG, DEBUG, {
+            int1 = userId
+            bool1 = isStrongBiometric
+        }, {"Face detected: userId: $int1, isStrongBiometric: $bool1"})
+    }
+
+    fun logFingerprintDetected(userId: Int, isStrongBiometric: Boolean) {
+        logBuffer.log(TAG, DEBUG, {
+            int1 = userId
+            bool1 = isStrongBiometric
+        }, {"Fingerprint detected: userId: $int1, isStrongBiometric: $bool1"})
+    }
+
     fun logFingerprintError(msgId: Int, originalErrMsg: String) {
         logBuffer.log(TAG, DEBUG, {
             str1 = originalErrMsg
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
index ce42534..0002ae9 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java
@@ -38,7 +38,6 @@
 import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.LayoutInflater;
-import android.view.ViewGroup;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -347,10 +346,9 @@
                 }
                 if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
                 updatePercentText();
-                addView(mBatteryPercentView,
-                        new ViewGroup.LayoutParams(
-                                LayoutParams.WRAP_CONTENT,
-                                LayoutParams.MATCH_PARENT));
+                addView(mBatteryPercentView, new LayoutParams(
+                        LayoutParams.WRAP_CONTENT,
+                        LayoutParams.MATCH_PARENT));
             }
         } else {
             if (showing) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
index 709ddf5..52312b8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
@@ -97,7 +97,6 @@
         val iconContentDescription = getIconContentDescription(newState)
         if (iconContentDescription != null) {
             iconView.contentDescription = iconContentDescription
-            iconViewOverlay.contentDescription = iconContentDescription
         }
 
         iconView.frame = 0
@@ -152,7 +151,7 @@
             STATE_AUTHENTICATING_ANIMATING_IN,
             STATE_AUTHENTICATING,
             STATE_PENDING_CONFIRMATION,
-            STATE_AUTHENTICATED -> R.string.accessibility_fingerprint_dialog_fingerprint_icon
+            STATE_AUTHENTICATED -> R.string.security_settings_sfps_enroll_find_sensor_message
             STATE_ERROR,
             STATE_HELP -> R.string.biometric_dialog_try_again
             else -> null
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index e698faf..08efd89 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -85,6 +85,8 @@
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.concurrency.Execution;
 
+import kotlin.Unit;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -98,8 +100,6 @@
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import kotlin.Unit;
-
 /**
  * Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the
  * appropriate biometric UI (e.g. BiometricDialogView).
@@ -872,7 +872,8 @@
     }
 
     /**
-     * Stores the callback received from {@link com.android.server.display.DisplayModeDirector}.
+     * Stores the callback received from
+     * {@link com.android.server.display.mode.DisplayModeDirector}.
      *
      * DisplayModeDirector implements {@link IUdfpsRefreshRateRequestCallback}
      * and registers it with this class by calling
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
index fabc1c1..e16121d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt
@@ -49,8 +49,8 @@
 
 /**
  * @property messagesToDefer messages that shouldn't show immediately when received, but may be
- * shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
- * percentage of all passed acquired frames.
+ *   shown later if the message is the most frequent acquiredInfo processed and meets [threshold]
+ *   percentage of all passed acquired frames.
  */
 open class BiometricMessageDeferral(
     private val messagesToDefer: Set<Int>,
@@ -127,8 +127,9 @@
     /**
      * Get the most frequent deferred message that meets the [threshold] percentage of processed
      * frames.
+     *
      * @return null if no acquiredInfo have been deferred OR deferred messages didn't meet the
-     * [threshold] percentage.
+     *   [threshold] percentage.
      */
     fun getDeferredMessage(): CharSequence? {
         mostFrequentAcquiredInfoToDefer?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
index ac6a22c..f7d87fc 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
@@ -492,7 +492,9 @@
             displayManager,
             handler,
             BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
-        ) { onOrientationChanged(reason) }
+        ) {
+            onOrientationChanged(reason)
+        }
 }
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
index 2d0d52e..231e7a4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.kt
@@ -348,6 +348,7 @@
 
     /**
      * Overrides non-bouncer show logic in shouldPauseAuth to still show icon.
+     *
      * @return whether the udfpsBouncer has been newly shown or hidden
      */
     private fun showUdfpsBouncer(show: Boolean): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
index 28bc2b7..6854b50 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/udfps/NormalizedTouchData.kt
@@ -76,5 +76,6 @@
         |          time: $time
         |  gestureStart: $gestureStart
         |}
-        """.trimMargin()
+        """
+            .trimMargin()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index cef415c..98a3e4b 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -130,7 +130,8 @@
         animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator);
 
         // For tablet docking animation, we don't play the background scrim.
-        if (!Utilities.isTablet(context)) {
+        // TODO(b/270524780): use utility to check for tablet instead. 
+        if (!Utilities.isLargeScreen(context)) {
             ValueAnimator scrimFadeInAnimator = ObjectAnimator.ofArgb(this,
                     "backgroundColor", Color.TRANSPARENT, SCRIM_COLOR);
             scrimFadeInAnimator.setDuration(SCRIM_FADE_DURATION);
diff --git a/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt b/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
index a0b19dc..c0e1717 100644
--- a/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/coroutine/ChannelExt.kt
@@ -26,7 +26,6 @@
     /**
      * Convenience wrapper around [SendChannel.trySend] that also logs on failure. This is the
      * equivalent of calling:
-     *
      * ```
      * sendChannel.trySend(element).onFailure {
      *     Log.e(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
index b3c18fb..3744344 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
@@ -86,6 +86,7 @@
      *
      * When the favorites for that application are returned, they will be removed from the auxiliary
      * file immediately, so they won't be retrieved again.
+     *
      * @param componentName the name of the service that provided the controls
      * @return a list of structures with favorites
      */
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index 822190f..3555d0a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -166,6 +166,19 @@
     )
 
     /**
+     * Removes favorites for a given component
+     * @param componentName the name of the service that provides the [Control]
+     * @return true when favorites is scheduled for deletion
+     */
+    fun removeFavorites(componentName: ComponentName): Boolean
+
+    /**
+     * Checks if the favorites can be removed. You can't remove components from the preferred list.
+     * @param componentName the name of the service that provides the [Control]
+     */
+    fun canRemoveFavorites(componentName: ComponentName): Boolean
+
+    /**
      * Replaces the favorites for the given structure.
      *
      * Calling this method will eliminate the previous selection of favorites and replace it with a
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 700f4f6..a171f43 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -499,6 +499,21 @@
         }
     }
 
+    override fun canRemoveFavorites(componentName: ComponentName): Boolean =
+            !authorizedPanelsRepository.getPreferredPackages().contains(componentName.packageName)
+
+    override fun removeFavorites(componentName: ComponentName): Boolean {
+        if (!confirmAvailability()) return false
+        if (!canRemoveFavorites(componentName)) return false
+
+        executor.execute {
+            Favorites.removeStructures(componentName)
+            authorizedPanelsRepository.removeAuthorizedPanels(setOf(componentName.packageName))
+            persistenceWrapper.storeFavorites(Favorites.getAllStructures())
+        }
+        return true
+    }
+
     override fun replaceFavoritesForStructure(structureInfo: StructureInfo) {
         if (!confirmAvailability()) return
         executor.execute {
@@ -657,10 +672,11 @@
         return true
     }
 
-    fun removeStructures(componentName: ComponentName) {
+    fun removeStructures(componentName: ComponentName): Boolean {
         val newFavMap = favMap.toMutableMap()
-        newFavMap.remove(componentName)
+        val removed = newFavMap.remove(componentName) != null
         favMap = newFavMap
+        return removed
     }
 
     fun addFavorite(
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 72c3a94..217f4d8 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -84,7 +84,7 @@
         private val BIND_FLAGS_PANEL = Context.BIND_AUTO_CREATE or Context.BIND_NOT_PERCEPTIBLE
     }
 
-    private val intent = Intent().apply {
+    private val intent = Intent(ControlsProviderService.SERVICE_CONTROLS).apply {
         component = componentName
         putExtra(CALLBACK_BUNDLE, Bundle().apply {
             putBinder(CALLBACK_TOKEN, token)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
index 3e672f3..ae9c37a 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepository.kt
@@ -26,6 +26,14 @@
     /** A set of package names that the user has previously authorized to show panels. */
     fun getAuthorizedPanels(): Set<String>
 
+    /** Preferred applications to query controls suggestions from */
+    fun getPreferredPackages(): Set<String>
+
     /** Adds [packageNames] to the set of packages that the user has authorized to show panels. */
     fun addAuthorizedPanels(packageNames: Set<String>)
+
+    /**
+     * Removes [packageNames] from the set of packages that the user has authorized to show panels.
+     */
+    fun removeAuthorizedPanels(packageNames: Set<String>)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
index f7e43a7..e51e832 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImpl.kt
@@ -37,10 +37,20 @@
         return getAuthorizedPanelsInternal(instantiateSharedPrefs())
     }
 
+    override fun getPreferredPackages(): Set<String> =
+        context.resources.getStringArray(R.array.config_controlsPreferredPackages).toSet()
+
     override fun addAuthorizedPanels(packageNames: Set<String>) {
         addAuthorizedPanelsInternal(instantiateSharedPrefs(), packageNames)
     }
 
+    override fun removeAuthorizedPanels(packageNames: Set<String>) {
+        with(instantiateSharedPrefs()) {
+            val currentSet = getAuthorizedPanelsInternal(this)
+            edit().putStringSet(KEY, currentSet - packageNames).apply()
+        }
+    }
+
     private fun getAuthorizedPanelsInternal(sharedPreferences: SharedPreferences): Set<String> {
         return sharedPreferences.getStringSet(KEY, emptySet())!!
     }
@@ -63,15 +73,7 @@
 
         // If we've never run this (i.e., the key doesn't exist), add the default packages
         if (sharedPref.getStringSet(KEY, null) == null) {
-            sharedPref
-                .edit()
-                .putStringSet(
-                    KEY,
-                    context.resources
-                        .getStringArray(R.array.config_controlsPreferredPackages)
-                        .toSet()
-                )
-                .apply()
+            sharedPref.edit().putStringSet(KEY, getPreferredPackages()).apply()
         }
         return sharedPref
     }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
index bb2e2d7..06d4a08 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/settings/ControlsSettingsDialogManager.kt
@@ -38,7 +38,6 @@
 
 /**
  * Manager to display a dialog to prompt user to enable controls related Settings:
- *
  * * [Settings.Secure.LOCKSCREEN_SHOW_CONTROLS]
  * * [Settings.Secure.LOCKSCREEN_ALLOW_TRIVIAL_CONTROLS]
  */
@@ -46,20 +45,19 @@
 
     /**
      * Shows the corresponding dialog. In order for a dialog to appear, the following must be true
-     *
      * * At least one of the Settings in [ControlsSettingsRepository] are `false`.
      * * The dialog has not been seen by the user too many times (as defined by
-     * [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
+     *   [MAX_NUMBER_ATTEMPTS_CONTROLS_DIALOG]).
      *
      * When the dialogs are shown, the following outcomes are possible:
      * * User cancels the dialog by clicking outside or going back: we register that the dialog was
-     * seen but the settings don't change.
+     *   seen but the settings don't change.
      * * User responds negatively to the dialog: we register that the user doesn't want to change
-     * the settings (dialog will not appear again) and the settings don't change.
+     *   the settings (dialog will not appear again) and the settings don't change.
      * * User responds positively to the dialog: the settings are set to `true` and the dialog will
-     * not appear again.
+     *   not appear again.
      * * SystemUI closes the dialogs (for example, the activity showing it is closed). In this case,
-     * we don't modify anything.
+     *   we don't modify anything.
      *
      * Of those four scenarios, only the first three will cause [onAttemptCompleted] to be called.
      * It will also be called if the dialogs are not shown.
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
index 3a3f9b4..bf0a692 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
@@ -68,7 +68,7 @@
 
         getLifecycle().addObserver(
             ControlsAnimations.observerForAnimations(
-                requireViewById<ViewGroup>(R.id.control_detail_root),
+                requireViewById(R.id.control_detail_root),
                 window,
                 intent,
                 !featureFlags.isEnabled(Flags.USE_APP_PANELS)
@@ -95,7 +95,7 @@
     override fun onStart() {
         super.onStart()
 
-        parent = requireViewById<ViewGroup>(R.id.global_actions_controls)
+        parent = requireViewById(R.id.control_detail_root)
         parent.alpha = 0f
         if (featureFlags.isEnabled(Flags.USE_APP_PANELS) && !keyguardStateController.isUnlocked) {
             controlsSettingsDialogManager.maybeShowDialog(this) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt
new file mode 100644
index 0000000..d6cfb79
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsDialogsFactory.kt
@@ -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.controls.ui
+
+import android.app.Dialog
+import android.content.Context
+import android.content.DialogInterface
+import com.android.systemui.R
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import java.util.function.Consumer
+import javax.inject.Inject
+
+class ControlsDialogsFactory(private val internalDialogFactory: (Context) -> SystemUIDialog) {
+
+    @Inject constructor() : this({ SystemUIDialog(it) })
+
+    fun createRemoveAppDialog(
+        context: Context,
+        appName: CharSequence,
+        response: Consumer<Boolean>
+    ): Dialog {
+        val listener =
+            DialogInterface.OnClickListener { _, which ->
+                response.accept(which == DialogInterface.BUTTON_POSITIVE)
+            }
+        return internalDialogFactory(context).apply {
+            setTitle(context.getString(R.string.controls_panel_remove_app_authorization, appName))
+            setCanceledOnTouchOutside(true)
+            setOnCancelListener { response.accept(false) }
+            setPositiveButton(R.string.controls_dialog_remove, listener)
+            setNeutralButton(R.string.cancel, listener)
+        }
+    }
+}
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 9405c60..c61dad6 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -21,6 +21,7 @@
 import android.animation.ObjectAnimator
 import android.app.Activity
 import android.app.ActivityOptions
+import android.app.Dialog
 import android.app.PendingIntent
 import android.content.ComponentName
 import android.content.Context
@@ -52,7 +53,6 @@
 import com.android.systemui.R
 import com.android.systemui.controls.ControlsMetricsLogger
 import com.android.systemui.controls.ControlsServiceInfo
-import com.android.systemui.controls.settings.ControlsSettingsRepository
 import com.android.systemui.controls.CustomIconCache
 import com.android.systemui.controls.controller.ControlsController
 import com.android.systemui.controls.controller.StructureInfo
@@ -64,6 +64,7 @@
 import com.android.systemui.controls.management.ControlsListingController
 import com.android.systemui.controls.management.ControlsProviderSelectorActivity
 import com.android.systemui.controls.panels.AuthorizedPanelsRepository
+import com.android.systemui.controls.settings.ControlsSettingsRepository
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
@@ -83,7 +84,7 @@
 import dagger.Lazy
 import java.io.PrintWriter
 import java.text.Collator
-import java.util.Optional
+import java.util.*
 import java.util.function.Consumer
 import javax.inject.Inject
 
@@ -108,6 +109,7 @@
         private val controlsSettingsRepository: ControlsSettingsRepository,
         private val authorizedPanelsRepository: AuthorizedPanelsRepository,
         private val featureFlags: FeatureFlags,
+        private val dialogsFactory: ControlsDialogsFactory,
         dumpManager: DumpManager
 ) : ControlsUiController, Dumpable {
 
@@ -122,6 +124,7 @@
         private const val ADD_CONTROLS_ID = 1L
         private const val ADD_APP_ID = 2L
         private const val EDIT_CONTROLS_ID = 3L
+        private const val REMOVE_APP_ID = 4L
     }
 
     private var selectedItem: SelectedItem = SelectedItem.EMPTY_SELECTION
@@ -151,6 +154,7 @@
 
     private var openAppIntent: Intent? = null
     private var overflowMenuAdapter: BaseAdapter? = null
+    private var removeAppDialog: Dialog? = null
 
     private val onSeedingComplete = Consumer<Boolean> {
         accepted ->
@@ -330,6 +334,31 @@
         }
     }
 
+    @VisibleForTesting
+    internal fun startRemovingApp(componentName: ComponentName, appName: CharSequence) {
+        removeAppDialog?.cancel()
+        removeAppDialog = dialogsFactory.createRemoveAppDialog(context, appName) {
+            if (!controlsController.get().removeFavorites(componentName)) {
+                return@createRemoveAppDialog
+            }
+            if (
+                    sharedPreferences.getString(PREF_COMPONENT, "") ==
+                    componentName.flattenToString()
+            ) {
+                sharedPreferences
+                        .edit()
+                        .remove(PREF_COMPONENT)
+                        .remove(PREF_STRUCTURE_OR_APP_NAME)
+                        .remove(PREF_IS_PANEL)
+                        .commit()
+            }
+
+            allStructures = controlsController.get().getFavorites()
+            selectedItem = getPreferredSelectedItem(allStructures)
+            reload(parent)
+        }.apply { show() }
+    }
+
     private fun startTargetedActivity(si: StructureInfo, klazz: Class<*>) {
         val i = Intent(activityContext, klazz)
         putIntentExtras(i, si)
@@ -433,7 +462,10 @@
         val currentApps = panelsAndStructures.map { it.componentName }.toSet()
         val allApps = controlsListingController.get()
                 .getCurrentServices().map { it.componentName }.toSet()
-        createMenu(extraApps = (allApps - currentApps).isNotEmpty())
+        createMenu(
+                selectionItem = selectionItem,
+                extraApps = (allApps - currentApps).isNotEmpty(),
+        )
     }
 
     private fun createPanelView(componentName: ComponentName) {
@@ -472,7 +504,7 @@
         }
     }
 
-    private fun createMenu(extraApps: Boolean) {
+    private fun createMenu(selectionItem: SelectionItem, extraApps: Boolean) {
         val isPanel = selectedItem is SelectedItem.PanelItem
         val selectedStructure = (selectedItem as? SelectedItem.StructureItem)?.structure
                 ?: EMPTY_STRUCTURE
@@ -490,6 +522,13 @@
                             ADD_APP_ID
                     ))
                 }
+                if (featureFlags.isEnabled(Flags.APP_PANELS_REMOVE_APPS_ALLOWED) &&
+                        controlsController.get().canRemoveFavorites(selectedItem.componentName)) {
+                    add(OverflowMenuAdapter.MenuItem(
+                            context.getText(R.string.controls_menu_remove),
+                            REMOVE_APP_ID,
+                    ))
+                }
             } else {
                 add(OverflowMenuAdapter.MenuItem(
                         context.getText(R.string.controls_menu_add),
@@ -529,6 +568,9 @@
                                 ADD_APP_ID -> startProviderSelectorActivity()
                                 ADD_CONTROLS_ID -> startFavoritingActivity(selectedStructure)
                                 EDIT_CONTROLS_ID -> startEditingActivity(selectedStructure)
+                                REMOVE_APP_ID -> startRemovingApp(
+                                        selectedStructure.componentName, selectionItem.appName
+                                )
                             }
                             dismiss()
                         }
@@ -546,8 +588,12 @@
             RenderInfo.registerComponentIcon(it.componentName, it.icon)
         }
 
-        var adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply {
-            addAll(items)
+        val adapter = ItemAdapter(context, R.layout.controls_spinner_item).apply {
+            add(selected)
+            addAll(items
+                    .filter { it !== selected }
+                    .sortedBy { it.appName.toString() }
+            )
         }
 
         val iconSize = context.resources
@@ -728,6 +774,7 @@
             it.value.dismiss()
         }
         controlActionCoordinator.closeDialogs()
+        removeAppDialog?.cancel()
     }
 
     override fun hide(parent: ViewGroup) {
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 3b6ab20..78e87ca 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/PanelTaskViewController.kt
@@ -71,7 +71,7 @@
                 taskView.post {
                     val roundedCorner =
                         activityContext.resources.getDimensionPixelSize(
-                            R.dimen.notification_corner_radius
+                            R.dimen.controls_panel_corner_radius
                         )
                     val radii = FloatArray(8) { roundedCorner.toFloat() }
                     taskView.background =
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 9921b1f..b86d419 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -47,10 +47,7 @@
 import com.android.systemui.recents.Recents
 import com.android.systemui.settings.dagger.MultiUserUtilsModule
 import com.android.systemui.shortcut.ShortcutKeyDispatcher
-import com.android.systemui.statusbar.notification.fsi.FsiChromeRepo
 import com.android.systemui.statusbar.notification.InstantAppNotifier
-import com.android.systemui.statusbar.notification.fsi.FsiChromeViewModelFactory
-import com.android.systemui.statusbar.notification.fsi.FsiChromeViewBinder
 import com.android.systemui.statusbar.phone.KeyguardLiftController
 import com.android.systemui.stylus.StylusUsiPowerStartable
 import com.android.systemui.temporarydisplay.chipbar.ChipbarCoordinator
@@ -91,24 +88,6 @@
     @ClassKey(ClipboardListener::class)
     abstract fun bindClipboardListener(sysui: ClipboardListener): CoreStartable
 
-    /** Inject into FsiChromeRepo.  */
-    @Binds
-    @IntoMap
-    @ClassKey(FsiChromeRepo::class)
-    abstract fun bindFSIChromeRepo(sysui: FsiChromeRepo): CoreStartable
-
-    /** Inject into FsiChromeWindowViewModel.  */
-    @Binds
-    @IntoMap
-    @ClassKey(FsiChromeViewModelFactory::class)
-    abstract fun bindFSIChromeWindowViewModel(sysui: FsiChromeViewModelFactory): CoreStartable
-
-    /** Inject into FsiChromeWindowBinder.  */
-    @Binds
-    @IntoMap
-    @ClassKey(FsiChromeViewBinder::class)
-    abstract fun bindFsiChromeWindowBinder(sysui: FsiChromeViewBinder): CoreStartable
-
     /** Inject into GlobalActionsComponent.  */
     @Binds
     @IntoMap
diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
index 84f83f1..45ff963 100644
--- a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
@@ -128,7 +128,6 @@
      *
      * This is equivalent of creating a listener manually and adding an event handler for the given
      * command, like so:
-     *
      * ```
      * class Demoable {
      *   private val demoHandler = object : DemoMode {
diff --git a/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt b/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt
new file mode 100644
index 0000000..1390b4d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt
@@ -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.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+import android.content.ComponentName
+
+/** Returns true if the admin of [userId] disallows keyguard shortcuts. */
+fun DevicePolicyManager.areKeyguardShortcutsDisabled(
+    admin: ComponentName? = null,
+    userId: Int
+): Boolean {
+    val flags = getKeyguardDisabledFeatures(admin, userId)
+    return flags and KEYGUARD_DISABLE_SHORTCUTS_ALL == KEYGUARD_DISABLE_SHORTCUTS_ALL ||
+        flags and KEYGUARD_DISABLE_FEATURES_ALL == KEYGUARD_DISABLE_FEATURES_ALL
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index c3bd5d9..ca1cef3 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -184,6 +184,7 @@
 
     /**
      * Ends the dream content and dream overlay animations, if they're currently running.
+     *
      * @see [AnimatorSet.end]
      */
     fun endAnimations() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index f282aae..9374ad9 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.dreams;
 
+import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_WINDOW_TITLE;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.drawable.ColorDrawable;
@@ -76,6 +78,7 @@
     private final ComponentName mLowLightDreamComponent;
     private final UiEventLogger mUiEventLogger;
     private final WindowManager mWindowManager;
+    private final String mWindowTitle;
 
     // A reference to the {@link Window} used to hold the dream overlay.
     private Window mWindow;
@@ -151,7 +154,8 @@
             TouchInsetManager touchInsetManager,
             @Nullable @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
                     ComponentName lowLightDreamComponent,
-            DreamOverlayCallbackController dreamOverlayCallbackController) {
+            DreamOverlayCallbackController dreamOverlayCallbackController,
+            @Named(DREAM_OVERLAY_WINDOW_TITLE) String windowTitle) {
         mContext = context;
         mExecutor = executor;
         mWindowManager = windowManager;
@@ -161,6 +165,7 @@
         mStateController = stateController;
         mUiEventLogger = uiEventLogger;
         mDreamOverlayCallbackController = dreamOverlayCallbackController;
+        mWindowTitle = windowTitle;
 
         final ViewModelStore viewModelStore = new ViewModelStore();
         final Complication.Host host =
@@ -277,7 +282,7 @@
     private boolean addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) {
         mWindow = new PhoneWindow(mContext);
         // Default to SystemUI name for TalkBack.
-        mWindow.setTitle("");
+        mWindow.setTitle(mWindowTitle);
         mWindow.setAttributes(layoutParams);
         mWindow.setWindowManager(null, layoutParams.token, "DreamOverlay", true);
 
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
index e39073b..ff1f312 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
@@ -28,6 +28,8 @@
 import com.android.systemui.CoreStartable;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.BcSmartspaceDataPlugin;
 import com.android.systemui.shared.condition.Monitor;
 import com.android.systemui.util.condition.ConditionalCoreStartable;
@@ -68,6 +70,7 @@
         private final DreamSmartspaceController mSmartSpaceController;
         private final DreamOverlayStateController mDreamOverlayStateController;
         private final SmartSpaceComplication mComplication;
+        private final FeatureFlags mFeatureFlags;
 
         private final BcSmartspaceDataPlugin.SmartspaceTargetListener mSmartspaceListener =
                 new BcSmartspaceDataPlugin.SmartspaceTargetListener() {
@@ -85,15 +88,21 @@
                 DreamOverlayStateController dreamOverlayStateController,
                 SmartSpaceComplication smartSpaceComplication,
                 DreamSmartspaceController smartSpaceController,
-                @Named(DREAM_PRETEXT_MONITOR) Monitor monitor) {
+                @Named(DREAM_PRETEXT_MONITOR) Monitor monitor,
+                FeatureFlags featureFlags) {
             super(monitor);
             mDreamOverlayStateController = dreamOverlayStateController;
             mComplication = smartSpaceComplication;
             mSmartSpaceController = smartSpaceController;
+            mFeatureFlags = featureFlags;
         }
 
         @Override
         public void onStart() {
+            if (mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)) {
+                return;
+            }
+
             mDreamOverlayStateController.addCallback(new DreamOverlayStateController.Callback() {
                 @Override
                 public void onStateChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index f598c36..f130026 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -23,6 +23,7 @@
 
 import com.android.dream.lowlight.dagger.LowLightDreamModule;
 import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
@@ -66,6 +67,8 @@
     String DREAM_SUPPORTED = "dream_supported";
     String DREAM_PRETEXT_CONDITIONS = "dream_pretext_conditions";
     String DREAM_PRETEXT_MONITOR = "dream_prtext_monitor";
+    String DREAM_OVERLAY_WINDOW_TITLE = "dream_overlay_window_title";
+
 
     /**
      * Provides the dream component
@@ -139,4 +142,11 @@
             @Named(DREAM_PRETEXT_CONDITIONS) Set<Condition> pretextConditions) {
         return new Monitor(executor, pretextConditions);
     }
+
+    /** */
+    @Provides
+    @Named(DREAM_OVERLAY_WINDOW_TITLE)
+    static String providesDreamOverlayWindowTitle(@Main Resources resources) {
+        return resources.getString(R.string.app_label);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index ab78b1b..3608b91 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -64,9 +64,6 @@
     // TODO(b/259130119): Tracking Bug
     val FSI_ON_DND_UPDATE = releasedFlag(259130119, "fsi_on_dnd_update")
 
-    // TODO(b/265804648): Tracking Bug
-    @JvmField val DISABLE_FSI = unreleasedFlag(265804648, "disable_fsi")
-
     // TODO(b/254512538): Tracking Bug
     val INSTANT_VOICE_REPLY = releasedFlag(111, "instant_voice_reply")
 
@@ -87,9 +84,6 @@
     val NOTIFICATION_GROUP_DISMISSAL_ANIMATION =
         releasedFlag(259217907, "notification_group_dismissal_animation")
 
-    // TODO(b/257506350): Tracking Bug
-    @JvmField val FSI_CHROME = unreleasedFlag(117, "fsi_chrome")
-
     @JvmField
     val SIMPLIFIED_APPEAR_FRACTION =
         unreleasedFlag(259395680, "simplified_appear_fraction", teamfood = true)
@@ -189,10 +183,6 @@
     @JvmField
     val REVAMPED_WALLPAPER_UI = releasedFlag(222, "revamped_wallpaper_ui")
 
-    /** A different path for unocclusion transitions back to keyguard */
-    // TODO(b/262859270): Tracking Bug
-    @JvmField val UNOCCLUSION_TRANSITION = releasedFlag(223, "unocclusion_transition")
-
     // flag for controlling auto pin confirmation and material u shapes in bouncer
     @JvmField
     val AUTO_PIN_CONFIRMATION =
@@ -234,6 +224,10 @@
     val SMARTSPACE_DATE_WEATHER_DECOUPLED =
         sysPropBooleanFlag(403, "persist.sysui.ss.dw_decoupled", default = true)
 
+    // TODO(b/270223352): Tracking Bug
+    @JvmField
+    val HIDE_SMARTSPACE_ON_DREAM_OVERLAY = unreleasedFlag(404, "hide_smartspace_on_dream_overlay")
+
     // 500 - quick settings
 
     val PEOPLE_TILE = resourceBooleanFlag(502, R.bool.flag_conversations, "people_tile")
@@ -373,15 +367,24 @@
     // TODO(b/267166152) : Tracking Bug
     val MEDIA_RETAIN_RECOMMENDATIONS = releasedFlag(916, "media_retain_recommendations")
 
+    // TODO(b/270437894): Tracking Bug
+    val MEDIA_REMOTE_RESUME = unreleasedFlag(917, "media_remote_resume")
+
     // 1000 - dock
     val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging")
 
     // TODO(b/254512758): Tracking Bug
     @JvmField val ROUNDED_BOX_RIPPLE = releasedFlag(1002, "rounded_box_ripple")
 
+    // TODO(b/270882464): Tracking Bug
+    val ENABLE_DOCK_SETUP_V2 = unreleasedFlag(1005, "enable_dock_setup_v2")
+
     // TODO(b/265045965): Tracking Bug
     val SHOW_LOWLIGHT_ON_DIRECT_BOOT = releasedFlag(1003, "show_lowlight_on_direct_boot")
 
+    @JvmField
+    val ENABLE_LOW_LIGHT_CLOCK_UNDOCKED = unreleasedFlag(1004, "enable_low_light_clock_undocked")
+
     // 1100 - windowing
     @Keep
     @JvmField
@@ -490,9 +493,9 @@
     val WM_ENABLE_PREDICTIVE_BACK_SYSUI =
         unreleasedFlag(1204, "persist.wm.debug.predictive_back_sysui_enable", teamfood = true)
 
-    // TODO(b/255697805): Tracking Bug
+    // TODO(b/270987164): Tracking Bug
     @JvmField
-    val TRACKPAD_GESTURE_BACK = unreleasedFlag(1205, "trackpad_gesture_back", teamfood = false)
+    val TRACKPAD_GESTURE_BACK = unreleasedFlag(1205, "trackpad_gesture_back", teamfood = true)
 
     // TODO(b/263826204): Tracking Bug
     @JvmField
@@ -622,11 +625,6 @@
     @JvmField
     val OUTPUT_SWITCHER_DEVICE_STATUS = releasedFlag(2502, "output_switcher_device_status")
 
-    // TODO(b/20911786): Tracking Bug
-    @JvmField
-    val OUTPUT_SWITCHER_SHOW_API_ENABLED =
-        releasedFlag(2503, "output_switcher_show_api_enabled", teamfood = true)
-
     // 2700 - unfold transitions
     // TODO(b/265764985): Tracking Bug
     @Keep
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index 0ca9115..57c4b36 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -945,9 +945,9 @@
             return false
         }
 
-        // We don't do the shared element on tablets because they're large and the smartspace has to
-        // fly across large distances, which is distracting.
-        if (Utilities.isTablet(context)) {
+        // We don't do the shared element on large screens because the smartspace has to fly across
+        // large distances, which is distracting.
+        if (Utilities.isLargeScreen(context)) {
             return false
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 02bee3e..2ad1ab7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -127,8 +127,6 @@
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.dagger.KeyguardModule;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -522,8 +520,6 @@
 
     private CentralSurfaces mCentralSurfaces;
 
-    private boolean mUnocclusionTransitionFlagEnabled = false;
-
     private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
             new DeviceConfig.OnPropertiesChangedListener() {
             @Override
@@ -970,9 +966,6 @@
                 public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
                         RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
                         IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
-                    if (!mUnocclusionTransitionFlagEnabled) {
-                        setOccluded(true /* isOccluded */, true /* animate */);
-                    }
                     if (apps == null || apps.length == 0 || apps[0] == null) {
                         if (DEBUG) {
                             Log.d(TAG, "No apps provided to the OccludeByDream runner; "
@@ -1023,7 +1016,7 @@
                             @Override
                             public void onAnimationEnd(Animator animation) {
                                 try {
-                                    if (!mIsCancelled && mUnocclusionTransitionFlagEnabled) {
+                                    if (!mIsCancelled) {
                                         // We're already on the main thread, don't queue this call
                                         handleSetOccluded(true /* isOccluded */,
                                                 false /* animate */);
@@ -1200,7 +1193,6 @@
             ScreenOnCoordinator screenOnCoordinator,
             InteractionJankMonitor interactionJankMonitor,
             DreamOverlayStateController dreamOverlayStateController,
-            FeatureFlags featureFlags,
             Lazy<ShadeController> shadeControllerLazy,
             Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy,
             Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
@@ -1259,7 +1251,6 @@
 
         mDreamOpenAnimationDuration = (int) DREAMING_ANIMATION_DURATION_MS;
         mDreamCloseAnimationDuration = (int) LOCKSCREEN_ANIMATION_DURATION_MS;
-        mUnocclusionTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
     }
 
     public void userActivity() {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 98d3570..47ef0fa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -39,7 +39,6 @@
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -113,7 +112,6 @@
             ScreenOnCoordinator screenOnCoordinator,
             InteractionJankMonitor interactionJankMonitor,
             DreamOverlayStateController dreamOverlayStateController,
-            FeatureFlags featureFlags,
             Lazy<ShadeController> shadeController,
             Lazy<NotificationShadeWindowController> notificationShadeWindowController,
             Lazy<ActivityLaunchAnimator> activityLaunchAnimator,
@@ -144,7 +142,6 @@
                 screenOnCoordinator,
                 interactionJankMonitor,
                 dreamOverlayStateController,
-                featureFlags,
                 shadeController,
                 notificationShadeWindowController,
                 activityLaunchAnimator,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
index be73f85..ef0c9a1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt
@@ -134,7 +134,9 @@
                 .flowOn(backgroundDispatcher)
                 .distinctUntilChanged()
                 .onEach { settingsValue = it }
-        ) { callbackFlowValue, _ -> callbackFlowValue }
+        ) { callbackFlowValue, _ ->
+            callbackFlowValue
+        }
 
     override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
         return if (controller.isZenAvailable) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
index 0066785..356a8fb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardQuickAffordanceLocalUserSelectionManager.kt
@@ -102,7 +102,8 @@
                     // setup).
                     emit(Unit)
                 }
-            ) { _, _ -> }
+            ) { _, _ ->
+            }
             .flatMapLatest {
                 conflatedCallbackFlow {
                     // We want to instantiate a new SharedPreferences instance each time either the
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
index baadc66..84abf57 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/BiometricSettingsRepository.kt
@@ -24,8 +24,10 @@
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback
 import android.os.Looper
 import android.os.UserHandle
+import android.util.Log
 import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.Dumpable
+import com.android.systemui.R
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.broadcast.BroadcastDispatcher
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
@@ -35,6 +37,7 @@
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.shared.model.DevicePosture
 import com.android.systemui.user.data.repository.UserRepository
 import java.io.PrintWriter
 import javax.inject.Inject
@@ -47,8 +50,10 @@
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.flow.transformLatest
@@ -82,6 +87,12 @@
 
     /** Whether fingerprint feature is enabled for the current user by the DevicePolicy */
     val isFingerprintEnabledByDevicePolicy: StateFlow<Boolean>
+
+    /**
+     * Whether face authentication is supported for the current device posture. Face auth can be
+     * restricted to specific postures using [R.integer.config_face_auth_supported_posture]
+     */
+    val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
 }
 
 @SysUISingleton
@@ -98,11 +109,27 @@
     @Background backgroundDispatcher: CoroutineDispatcher,
     biometricManager: BiometricManager?,
     @Main looper: Looper,
+    devicePostureRepository: DevicePostureRepository,
     dumpManager: DumpManager,
 ) : BiometricSettingsRepository, Dumpable {
 
+    override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
+
     init {
         dumpManager.registerDumpable(this)
+        val configFaceAuthSupportedPosture =
+            DevicePosture.toPosture(
+                context.resources.getInteger(R.integer.config_face_auth_supported_posture)
+            )
+        isFaceAuthSupportedInCurrentPosture =
+            if (configFaceAuthSupportedPosture == DevicePosture.UNKNOWN) {
+                    flowOf(true)
+                } else {
+                    devicePostureRepository.currentDevicePosture.map {
+                        it == configFaceAuthSupportedPosture
+                    }
+                }
+                .onEach { Log.d(TAG, "isFaceAuthSupportedInCurrentPosture value changed to: $it") }
     }
 
     override fun dump(pw: PrintWriter, args: Array<String?>) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt
new file mode 100644
index 0000000..adb1e01
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DevicePostureRepository.kt
@@ -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.keyguard.data.repository
+
+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.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
+import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+
+/** Provide current device posture state. */
+interface DevicePostureRepository {
+    /** Provides the current device posture. */
+    val currentDevicePosture: Flow<DevicePosture>
+}
+
+@SysUISingleton
+class DevicePostureRepositoryImpl
+@Inject
+constructor(private val postureController: DevicePostureController) : DevicePostureRepository {
+    override val currentDevicePosture: Flow<DevicePosture>
+        get() = conflatedCallbackFlow {
+            val sendPostureUpdate = { posture: Int ->
+                val currentDevicePosture = DevicePosture.toPosture(posture)
+                trySendWithFailureLogging(
+                    currentDevicePosture,
+                    TAG,
+                    "Error sending posture update to $currentDevicePosture"
+                )
+            }
+            val callback = DevicePostureController.Callback { sendPostureUpdate(it) }
+            postureController.addCallback(callback)
+            sendPostureUpdate(postureController.devicePosture)
+
+            awaitClose { postureController.removeCallback(callback) }
+        }
+
+    companion object {
+        const val TAG = "PostureRepositoryImpl"
+    }
+}
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 0e85347..86e5cd7 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
@@ -53,6 +53,7 @@
     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
@@ -134,6 +135,7 @@
     override val primaryBouncerScrimmed = _primaryBouncerScrimmed.asStateFlow()
     /**
      * 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
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index a3b3d0f..76f20d25 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -80,6 +80,9 @@
      */
     val isKeyguardShowing: Flow<Boolean>
 
+    /** Is the keyguard in a unlocked state? */
+    val isKeyguardUnlocked: Flow<Boolean>
+
     /** Is an activity showing over the keyguard? */
     val isKeyguardOccluded: Flow<Boolean>
 
@@ -278,6 +281,31 @@
             }
             .distinctUntilChanged()
 
+    override val isKeyguardUnlocked: Flow<Boolean> =
+        conflatedCallbackFlow {
+                val callback =
+                    object : KeyguardStateController.Callback {
+                        override fun onUnlockedChanged() {
+                            trySendWithFailureLogging(
+                                keyguardStateController.isUnlocked,
+                                TAG,
+                                "updated isKeyguardUnlocked"
+                            )
+                        }
+                    }
+
+                keyguardStateController.addCallback(callback)
+                // Adding the callback does not send an initial update.
+                trySendWithFailureLogging(
+                    keyguardStateController.isUnlocked,
+                    TAG,
+                    "initial isKeyguardUnlocked"
+                )
+
+                awaitClose { keyguardStateController.removeCallback(callback) }
+            }
+            .distinctUntilChanged()
+
     override val isKeyguardGoingAway: Flow<Boolean> = conflatedCallbackFlow {
         val callback =
             object : KeyguardStateController.Callback {
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 4a262f5..f27f899 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,6 +31,8 @@
     @Binds
     fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository
 
+    @Binds fun devicePostureRepository(impl: DevicePostureRepositoryImpl): DevicePostureRepository
+
     @Binds
     fun biometricSettingsRepository(
         impl: BiometricSettingsRepositoryImpl
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
index 0c4bca6..100bc59 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt
@@ -68,8 +68,11 @@
     /**
      * Begin a transition from one state to another. Transitions are interruptible, and will issue a
      * [TransitionStep] with state = [TransitionState.CANCELED] before beginning the next one.
+     *
+     * When canceled, there are two options: to continue from the current position of the prior
+     * transition, or to reset the position. When [resetIfCanceled] == true, it will do the latter.
      */
-    fun startTransition(info: TransitionInfo): UUID?
+    fun startTransition(info: TransitionInfo, resetIfCanceled: Boolean = false): UUID?
 
     /**
      * Allows manual control of a transition. When calling [startTransition], the consumer must pass
@@ -130,7 +133,10 @@
         )
     }
 
-    override fun startTransition(info: TransitionInfo): UUID? {
+    override fun startTransition(
+        info: TransitionInfo,
+        resetIfCanceled: Boolean,
+    ): UUID? {
         if (lastStep.from == info.from && lastStep.to == info.to) {
             Log.i(TAG, "Duplicate call to start the transition, rejecting: $info")
             return null
@@ -138,7 +144,11 @@
         val startingValue =
             if (lastStep.transitionState != TransitionState.FINISHED) {
                 Log.i(TAG, "Transition still active: $lastStep, canceling")
-                lastStep.value
+                if (resetIfCanceled) {
+                    0f
+                } else {
+                    lastStep.value
+                }
             } else {
                 0f
             }
@@ -227,10 +237,7 @@
     }
 
     private fun trace(step: TransitionStep, isManual: Boolean) {
-        if (
-            step.transitionState != TransitionState.STARTED &&
-                step.transitionState != TransitionState.FINISHED
-        ) {
+        if (step.transitionState == TransitionState.RUNNING) {
             return
         }
         val traceName =
@@ -243,7 +250,10 @@
         val traceCookie = traceName.hashCode()
         if (step.transitionState == TransitionState.STARTED) {
             Trace.beginAsyncSection(traceName, traceCookie)
-        } else if (step.transitionState == TransitionState.FINISHED) {
+        } else if (
+            step.transitionState == TransitionState.FINISHED ||
+                step.transitionState == TransitionState.CANCELED
+        ) {
             Trace.endAsyncSection(traceName, traceCookie)
         }
     }
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 0140529..eae40d6 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
@@ -50,6 +50,7 @@
 
     /**
      * Sets the correct bouncer states to show the alternate bouncer if it can show.
+     *
      * @return whether alternateBouncer is visible
      */
     fun show(): Boolean {
@@ -74,6 +75,7 @@
      * Sets the correct bouncer states to hide the bouncer. Should only be called through
      * StatusBarKeyguardViewManager until ScrimController is refactored to use
      * alternateBouncerInteractor.
+     *
      * @return true if the alternate bouncer was newly hidden, else false.
      */
     fun hide(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
index 310f44d..e6568f2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -71,8 +71,7 @@
                         isPrimaryBouncerShowing,
                         lastStartedTransitionStep,
                         wakefulnessState,
-                        isAodAvailable
-                    ) ->
+                        isAodAvailable) ->
                     if (
                         !isAlternateBouncerShowing &&
                             !isPrimaryBouncerShowing &&
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 8715d1f..3beac0b 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,7 +34,6 @@
 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
 
@@ -57,14 +56,7 @@
 
     private fun listenForDreamingToLockscreen() {
         scope.launch {
-            // 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()
+            keyguardInteractor.isAbleToDream
                 .sample(
                     combine(
                         keyguardInteractor.dozeTransitionModel,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
index d01f489..911861d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromLockscreenTransitionInteractor.kt
@@ -130,55 +130,59 @@
             shadeRepository.shadeModel
                 .sample(
                     combine(
-                        keyguardTransitionInteractor.finishedKeyguardState,
+                        keyguardTransitionInteractor.startedKeyguardTransitionStep,
                         keyguardInteractor.statusBarState,
-                        ::Pair
+                        keyguardInteractor.isKeyguardUnlocked,
+                        ::toTriple
                     ),
-                    ::toTriple
+                    ::toQuad
                 )
-                .collect { (shadeModel, keyguardState, statusBarState) ->
+                .collect { (shadeModel, keyguardState, statusBarState, isKeyguardUnlocked) ->
                     val id = transitionId
                     if (id != null) {
-                        // An existing `id` means a transition is started, and calls to
-                        // `updateTransition` will control it until FINISHED or CANCELED
-                        var nextState =
-                            if (shadeModel.expansionAmount == 0f) {
-                                TransitionState.FINISHED
-                            } else if (shadeModel.expansionAmount == 1f) {
-                                TransitionState.CANCELED
-                            } else {
-                                TransitionState.RUNNING
-                            }
-                        keyguardTransitionRepository.updateTransition(
-                            id,
-                            1f - shadeModel.expansionAmount,
-                            nextState,
-                        )
-
-                        if (
-                            nextState == TransitionState.CANCELED ||
-                                nextState == TransitionState.FINISHED
-                        ) {
-                            transitionId = null
-                        }
-
-                        // If canceled, just put the state back
-                        if (nextState == TransitionState.CANCELED) {
-                            keyguardTransitionRepository.startTransition(
-                                TransitionInfo(
-                                    ownerName = name,
-                                    from = KeyguardState.PRIMARY_BOUNCER,
-                                    to = KeyguardState.LOCKSCREEN,
-                                    animator = getAnimator(0.milliseconds)
-                                )
+                        if (keyguardState.to == KeyguardState.PRIMARY_BOUNCER) {
+                            // An existing `id` means a transition is started, and calls to
+                            // `updateTransition` will control it until FINISHED or CANCELED
+                            var nextState =
+                                if (shadeModel.expansionAmount == 0f) {
+                                    TransitionState.FINISHED
+                                } else if (shadeModel.expansionAmount == 1f) {
+                                    TransitionState.CANCELED
+                                } else {
+                                    TransitionState.RUNNING
+                                }
+                            keyguardTransitionRepository.updateTransition(
+                                id,
+                                1f - shadeModel.expansionAmount,
+                                nextState,
                             )
+
+                            if (
+                                nextState == TransitionState.CANCELED ||
+                                    nextState == TransitionState.FINISHED
+                            ) {
+                                transitionId = null
+                            }
+
+                            // If canceled, just put the state back
+                            if (nextState == TransitionState.CANCELED) {
+                                keyguardTransitionRepository.startTransition(
+                                    TransitionInfo(
+                                        ownerName = name,
+                                        from = KeyguardState.PRIMARY_BOUNCER,
+                                        to = KeyguardState.LOCKSCREEN,
+                                        animator = getAnimator(0.milliseconds)
+                                    )
+                                )
+                            }
                         }
                     } else {
                         // TODO (b/251849525): Remove statusbarstate check when that state is
                         // integrated into KeyguardTransitionRepository
                         if (
-                            keyguardState == KeyguardState.LOCKSCREEN &&
+                            keyguardState.to == KeyguardState.LOCKSCREEN &&
                                 shadeModel.isUserDragging &&
+                                !isKeyguardUnlocked &&
                                 statusBarState == KEYGUARD
                         ) {
                             transitionId =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
index b59b413..94961cb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromPrimaryBouncerTransitionInteractor.kt
@@ -17,6 +17,9 @@
 package com.android.systemui.keyguard.domain.interactor
 
 import android.animation.ValueAnimator
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Password
+import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
@@ -26,6 +29,8 @@
 import com.android.systemui.keyguard.shared.model.WakefulnessState
 import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
+import kotlin.time.Duration
+import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
@@ -37,7 +42,8 @@
     @Application private val scope: CoroutineScope,
     private val keyguardInteractor: KeyguardInteractor,
     private val keyguardTransitionRepository: KeyguardTransitionRepository,
-    private val keyguardTransitionInteractor: KeyguardTransitionInteractor
+    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
+    private val keyguardSecurityModel: KeyguardSecurityModel,
 ) : TransitionInteractor(FromPrimaryBouncerTransitionInteractor::class.simpleName!!) {
 
     override fun start() {
@@ -93,31 +99,47 @@
     private fun listenForPrimaryBouncerToGone() {
         scope.launch {
             keyguardInteractor.isKeyguardGoingAway
-                .sample(keyguardTransitionInteractor.finishedKeyguardState) { a, b -> Pair(a, b) }
-                .collect { pair ->
-                    val (isKeyguardGoingAway, keyguardState) = pair
-                    if (isKeyguardGoingAway && keyguardState == KeyguardState.PRIMARY_BOUNCER) {
+                .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
+                .collect { (isKeyguardGoingAway, lastStartedTransitionStep) ->
+                    if (
+                        isKeyguardGoingAway &&
+                            lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER
+                    ) {
+                        val securityMode =
+                            keyguardSecurityModel.getSecurityMode(
+                                KeyguardUpdateMonitor.getCurrentUser()
+                            )
+                        // IME for password requires a slightly faster animation
+                        val duration =
+                            if (securityMode == Password) {
+                                TO_GONE_SHORT_DURATION
+                            } else {
+                                TO_GONE_DURATION
+                            }
                         keyguardTransitionRepository.startTransition(
                             TransitionInfo(
                                 ownerName = name,
                                 from = KeyguardState.PRIMARY_BOUNCER,
                                 to = KeyguardState.GONE,
-                                animator = getAnimator(),
-                            )
+                                animator = getAnimator(duration),
+                            ),
+                            resetIfCanceled = true,
                         )
                     }
                 }
         }
     }
 
-    private fun getAnimator(): ValueAnimator {
+    private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator {
         return ValueAnimator().apply {
             setInterpolator(Interpolators.LINEAR)
-            setDuration(TRANSITION_DURATION_MS)
+            setDuration(duration.inWholeMilliseconds)
         }
     }
 
     companion object {
-        private const val TRANSITION_DURATION_MS = 300L
+        private val DEFAULT_DURATION = 300.milliseconds
+        val TO_GONE_DURATION = 250.milliseconds
+        val TO_GONE_SHORT_DURATION = 200.milliseconds
     }
 }
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 d25aff0a..ec99049 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
@@ -33,7 +33,9 @@
 import com.android.systemui.keyguard.shared.model.DozeTransitionModel
 import com.android.systemui.keyguard.shared.model.StatusBarState
 import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isWakingOrStartingToWake
 import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.delay
@@ -95,6 +97,9 @@
         awaitClose { commandQueue.removeCallback(callback) }
     }
 
+    /** The device wake/sleep state */
+    val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
+
     /**
      * Dozing and dreaming have overlapping events. If the doze state remains in FINISH, it means
      * that doze mode is not running and DREAMING is ok to commence.
@@ -109,6 +114,12 @@
                     isDreaming && isDozeOff(dozeTransitionModel.to)
                 }
             )
+            .sample(
+                wakefulnessModel,
+                { isAbleToDream, wakefulnessModel ->
+                    isAbleToDream && isWakingOrStartingToWake(wakefulnessModel)
+                }
+            )
             .flatMapLatest { isAbleToDream ->
                 flow {
                     delay(50)
@@ -119,6 +130,8 @@
 
     /** Whether the keyguard is showing or not. */
     val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
+    /** Whether the keyguard is unlocked or not. */
+    val isKeyguardUnlocked: Flow<Boolean> = repository.isKeyguardUnlocked
     /** Whether the keyguard is occluded (covered by an activity). */
     val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded
     /** Whether the keyguard is going away. */
@@ -127,8 +140,6 @@
     val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerVisible
     /** Whether the alternate bouncer is showing or not. */
     val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
-    /** The device wake/sleep state */
-    val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
     /** Observable for the [StatusBarState] */
     val statusBarState: Flow<StatusBarState> = repository.statusBarState
     /**
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 dfbe1c2..bc3c720 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
@@ -26,6 +26,7 @@
 import com.android.systemui.animation.Expandable
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
@@ -119,7 +120,7 @@
      * Notifies that a quick affordance has been "triggered" (clicked) by the user.
      *
      * @param configKey The configuration key corresponding to the [KeyguardQuickAffordanceModel] of
-     * the affordance that was clicked
+     *   the affordance that was clicked
      * @param expandable An optional [Expandable] for the activity- or dialog-launch animation
      */
     fun onQuickAffordanceTriggered(
@@ -198,9 +199,9 @@
      *
      * @param slotId The ID of the slot.
      * @param affordanceId The ID of the affordance to remove; if `null`, removes all affordances
-     * from the slot.
+     *   from the slot.
      * @return `true` if the affordance was successfully removed; `false` otherwise (for example, if
-     * the affordance was not on the slot to begin with).
+     *   the affordance was not on the slot to begin with).
      */
     suspend fun unselect(slotId: String, affordanceId: String?): Boolean {
         check(isUsingRepository)
@@ -410,16 +411,10 @@
         )
     }
 
-    private suspend fun isFeatureDisabledByDevicePolicy(): Boolean {
-        val flags =
-            withContext(backgroundDispatcher) {
-                devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId)
-            }
-        val flagsToCheck =
-            DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL or
-                DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
-        return flagsToCheck and flags != 0
-    }
+    private suspend fun isFeatureDisabledByDevicePolicy(): Boolean =
+        withContext(backgroundDispatcher) {
+            devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
+        }
 
     companion object {
         private const val TAG = "KeyguardQuickAffordanceInteractor"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
index 51b0277..e650b9f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
@@ -61,7 +61,15 @@
         }
 
         scope.launch {
-            keyguardInteractor.isDreaming.collect { logger.log(TAG, VERBOSE, "isDreaming", it) }
+            keyguardInteractor.isAbleToDream.collect {
+                logger.log(TAG, VERBOSE, "isAbleToDream", it)
+            }
+        }
+
+        scope.launch {
+            keyguardInteractor.isKeyguardOccluded.collect {
+                logger.log(TAG, VERBOSE, "isOccluded", it)
+            }
         }
 
         scope.launch {
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 1b7da5b..3c0ec35 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
@@ -78,6 +78,10 @@
     val occludedToLockscreenTransition: Flow<TransitionStep> =
         repository.transition(OCCLUDED, LOCKSCREEN)
 
+    /** PRIMARY_BOUNCER->GONE transition information. */
+    val primaryBouncerToGoneTransition: Flow<TransitionStep> =
+        repository.transition(PRIMARY_BOUNCER, GONE)
+
     /**
      * AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <->
      * Lockscreen (0f).
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt
new file mode 100644
index 0000000..fff7cfe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/DevicePosture.kt
@@ -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.keyguard.shared.model
+
+import com.android.systemui.statusbar.policy.DevicePostureController
+
+/** Represents the possible posture states of the device. */
+enum class DevicePosture {
+    UNKNOWN,
+    CLOSED,
+    HALF_OPENED,
+    OPENED,
+    FLIPPED;
+
+    companion object {
+        fun toPosture(@DevicePostureController.DevicePostureInt posture: Int): DevicePosture {
+            return when (posture) {
+                DevicePostureController.DEVICE_POSTURE_CLOSED -> CLOSED
+                DevicePostureController.DEVICE_POSTURE_HALF_OPENED -> HALF_OPENED
+                DevicePostureController.DEVICE_POSTURE_OPENED -> OPENED
+                DevicePostureController.DEVICE_POSTURE_FLIPPED -> FLIPPED
+                DevicePostureController.DEVICE_POSTURE_UNKNOWN -> UNKNOWN
+                else -> UNKNOWN
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt
new file mode 100644
index 0000000..a79513e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.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.systemui.keyguard.shared.model
+
+import android.hardware.face.FaceAuthenticateOptions
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_ASSISTANT_VISIBLE
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_STARTED_WAKING_UP
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_UDFPS_POINTER_DOWN
+import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_UNKNOWN
+import android.hardware.face.FaceAuthenticateOptions.AuthenticateReason
+import android.os.PowerManager
+import android.os.PowerManager.WAKE_REASON_UNKNOWN
+import android.util.Log
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+import com.android.keyguard.FaceAuthUiEvent
+
+/**
+ * Wrapper for [FaceAuthenticateOptions] to convert SystemUI values to their corresponding value in
+ * [FaceAuthenticateOptions].
+ */
+data class SysUiFaceAuthenticateOptions(
+        val userId: Int,
+        private val faceAuthUiEvent: UiEventLogger.UiEventEnum,
+        @PowerManager.WakeReason val wakeReason: Int = WAKE_REASON_UNKNOWN
+) {
+    val authenticateReason = setAuthenticateReason(faceAuthUiEvent)
+
+    /**
+     * The [FaceAuthUiEvent] for this operation. This method converts the UiEvent to the framework
+     * [AuthenticateReason].
+     */
+    @AuthenticateReason
+    fun setAuthenticateReason(uiEvent: UiEventLogger.UiEventEnum): Int {
+        return when (uiEvent) {
+            FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP -> {
+                AUTHENTICATE_REASON_STARTED_WAKING_UP
+            }
+            FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN,
+            FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN -> {
+                AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN
+            }
+            FaceAuthUiEvent.FACE_AUTH_UPDATED_ASSISTANT_VISIBILITY_CHANGED -> {
+                AUTHENTICATE_REASON_ASSISTANT_VISIBLE
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN -> {
+                AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_NOTIFICATION_PANEL_CLICKED -> {
+                AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_OCCLUDING_APP_REQUESTED -> {
+                AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_PICK_UP_GESTURE_TRIGGERED -> {
+                AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER -> {
+                AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER
+            }
+            FaceAuthUiEvent.FACE_AUTH_TRIGGERED_UDFPS_POINTER_DOWN -> {
+                AUTHENTICATE_REASON_UDFPS_POINTER_DOWN
+            }
+            else -> {
+                Log.e("FaceAuthenticateOptions", " unmapped FaceAuthUiEvent $uiEvent")
+                AUTHENTICATE_REASON_UNKNOWN
+            }
+        }
+    }
+
+    /** Builds the instance. */
+    fun toFaceAuthenticateOptions(): FaceAuthenticateOptions {
+        return FaceAuthenticateOptions.Builder()
+            .setUserId(userId)
+            .setAuthenticateReason(authenticateReason)
+            .setWakeReason(wakeReason)
+            .build()
+    }
+}
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 ab009f4..2a9060f6 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
@@ -342,7 +342,13 @@
         if (viewModel.isClickable) {
             if (viewModel.useLongPress) {
                 view.setOnTouchListener(
-                    OnTouchListener(view, viewModel, messageDisplayer, vibratorHelper)
+                    OnTouchListener(
+                        view,
+                        viewModel,
+                        messageDisplayer,
+                        vibratorHelper,
+                        falsingManager,
+                    )
                 )
             } else {
                 view.setOnClickListener(OnClickListener(viewModel, checkNotNull(falsingManager)))
@@ -371,6 +377,7 @@
         private val viewModel: KeyguardQuickAffordanceViewModel,
         private val messageDisplayer: (Int) -> Unit,
         private val vibratorHelper: VibratorHelper?,
+        private val falsingManager: FalsingManager?,
     ) : View.OnTouchListener {
 
         private val longPressDurationMs = ViewConfiguration.getLongPressTimeout().toLong()
@@ -395,7 +402,14 @@
                                     .scaleY(PRESSED_SCALE)
                                     .setDuration(longPressDurationMs)
                                     .withEndAction {
-                                        dispatchClick(viewModel.configKey)
+                                        if (
+                                            falsingManager
+                                                ?.isFalseLongTap(
+                                                    FalsingManager.MODERATE_PENALTY
+                                                ) == false
+                                        ) {
+                                            dispatchClick(viewModel.configKey)
+                                        }
                                         cancel()
                                     }
                         }
@@ -421,7 +435,8 @@
                         // the pointer performs a click.
                         if (
                             viewModel.configKey != null &&
-                                distanceMoved(event) <= ViewConfiguration.getTouchSlop()
+                                distanceMoved(event) <= ViewConfiguration.getTouchSlop() &&
+                                falsingManager?.isFalseTap(FalsingManager.NO_PENALTY) == false
                         ) {
                             dispatchClick(viewModel.configKey)
                         }
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 7db567b..2337ffc 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
@@ -31,6 +31,7 @@
 import com.android.systemui.keyguard.data.BouncerViewDelegate
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
 import com.android.systemui.lifecycle.repeatWhenAttached
 import com.android.systemui.plugins.ActivityStarter
 import kotlinx.coroutines.awaitCancellation
@@ -44,6 +45,7 @@
     fun bind(
         view: ViewGroup,
         viewModel: KeyguardBouncerViewModel,
+        primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
         componentFactory: KeyguardBouncerComponent.Factory
     ) {
         // Builds the KeyguardSecurityContainerController from bouncer view group.
@@ -145,6 +147,12 @@
                     }
 
                     launch {
+                        primaryBouncerToGoneTransitionViewModel.bouncerAlpha.collect { alpha ->
+                            securityContainerController.setAlpha(alpha)
+                        }
+                    }
+
+                    launch {
                         viewModel.bouncerExpansionAmount
                             .filter { it == EXPANSION_VISIBLE }
                             .collect {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
index ef3f242..8671753 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardLongPressViewBinder.kt
@@ -34,7 +34,7 @@
      * @param viewModel The view-model that models the UI state.
      * @param onSingleTap A callback to invoke when the system decides that there was a single tap.
      * @param falsingManager [FalsingManager] for making sure the long-press didn't just happen in
-     * the user's pocket.
+     *   the user's pocket.
      */
     @JvmStatic
     fun bind(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
index 1e3b60c..ab9e6a4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModel.kt
@@ -135,7 +135,7 @@
      *
      * @param initiallySelectedSlotId The ID of the initial slot to render as the selected one.
      * @param shouldHighlightSelectedAffordance Whether the selected quick affordance should be
-     * highlighted (while all others are dimmed to make the selected one stand out).
+     *   highlighted (while all others are dimmed to make the selected one stand out).
      */
     fun enablePreviewMode(
         initiallySelectedSlotId: String?,
@@ -187,6 +187,7 @@
                             previewMode.isInPreviewMode &&
                                 previewMode.shouldHighlightSelectedAffordance &&
                                 !isSelected,
+                        forceInactive = previewMode.isInPreviewMode
                     )
                 }
                 .distinctUntilChanged()
@@ -198,6 +199,7 @@
         isClickable: Boolean,
         isSelected: Boolean,
         isDimmed: Boolean,
+        forceInactive: Boolean,
     ): KeyguardQuickAffordanceViewModel {
         return when (this) {
             is KeyguardQuickAffordanceModel.Visible ->
@@ -213,7 +215,7 @@
                         )
                     },
                     isClickable = isClickable,
-                    isActivated = activationState is ActivationState.Active,
+                    isActivated = !forceInactive && activationState is ActivationState.Active,
                     isSelected = isSelected,
                     useLongPress = quickAffordanceInteractor.useLongPress,
                     isDimmed = isDimmed,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
new file mode 100644
index 0000000..0890791
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModel.kt
@@ -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.keyguard.ui.viewmodel
+
+import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GONE_DURATION
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import javax.inject.Inject
+import kotlin.time.Duration.Companion.milliseconds
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * Breaks down PRIMARY_BOUNCER->GONE transition into discrete steps for corresponding views to
+ * consume.
+ */
+@SysUISingleton
+class PrimaryBouncerToGoneTransitionViewModel
+@Inject
+constructor(
+    private val interactor: KeyguardTransitionInteractor,
+) {
+    private val transitionAnimation =
+        KeyguardTransitionAnimationFlow(
+            transitionDuration = TO_GONE_DURATION,
+            transitionFlow = interactor.primaryBouncerToGoneTransition,
+        )
+
+    /** Bouncer container alpha */
+    val bouncerAlpha: Flow<Float> =
+        transitionAnimation.createFlow(
+            duration = 200.milliseconds,
+            onStep = { 1f - it },
+        )
+
+    /** Scrim alpha */
+    val scrimAlpha: Flow<Float> =
+        transitionAnimation.createFlow(
+            duration = TO_GONE_DURATION,
+            interpolator = EMPHASIZED_ACCELERATE,
+            onStep = { 1f - it },
+        )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index d69ac7f..34a6740 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -47,13 +47,13 @@
  * fresh one.
  *
  * @param coroutineContext An optional [CoroutineContext] to replace the dispatcher [block] is
- * invoked on.
+ *   invoked on.
  * @param block The block of code that should be run when the view becomes attached. It can end up
- * being invoked multiple times if the view is reattached after being detached.
+ *   being invoked multiple times if the view is reattached after being detached.
  * @return A [DisposableHandle] to invoke when the caller of the function destroys its [View] and is
- * no longer interested in the [block] being run the next time its attached. Calling this is an
- * optional optimization as the logic will be properly cleaned up and destroyed each time the view
- * is detached. Using this is not *thread-safe* and should only be used on the main thread.
+ *   no longer interested in the [block] being run the next time its attached. Calling this is an
+ *   optional optimization as the logic will be properly cleaned up and destroyed each time the view
+ *   is detached. Using this is not *thread-safe* and should only be used on the main thread.
  */
 @MainThread
 fun View.repeatWhenAttached(
@@ -125,7 +125,6 @@
  * The implementation requires the caller to call [onCreate] and [onDestroy] when the view is
  * attached to or detached from a view hierarchy. After [onCreate] and before [onDestroy] is called,
  * the implementation monitors window state in the following way
- *
  * * If the window is not visible, we are in the [Lifecycle.State.CREATED] state
  * * If the window is visible but not focused, we are in the [Lifecycle.State.STARTED] state
  * * If the window is visible and focused, we are in the [Lifecycle.State.RESUMED] state
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
index f7349a2..647e3a1 100644
--- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -16,7 +16,6 @@
  * Helper class for logging for [com.android.keyguard.faceauth.KeyguardFaceAuthManager]
  *
  * To enable logcat echoing for an entire buffer:
- *
  * ```
  *   adb shell settings put global systemui/buffer/KeyguardFaceAuthManagerLog <logLevel>
  *
diff --git a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
index 5acaa46..edc278d 100644
--- a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
@@ -33,7 +33,6 @@
  * 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>
  *
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 220993f..ca1ed1f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -62,6 +62,15 @@
         return factory.create("NotifLog", maxSize, false /* systrace */);
     }
 
+    /** Provides a logging buffer for all logs related to notifications on the lockscreen. */
+    @Provides
+    @SysUISingleton
+    @NotificationLockscreenLog
+    public static LogBuffer provideNotificationLockScreenLogBuffer(
+            LogBufferFactory factory) {
+        return factory.create("NotifLockscreenLog", 50, false /* systrace */);
+    }
+
     /** Provides a logging buffer for logs related to heads up presentation of notifications. */
     @Provides
     @SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
new file mode 100644
index 0000000..a2d381e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
@@ -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.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.plugins.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for notification & lockscreen related messages. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotificationLockscreenLog {
+}
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 1712dab..29f273a 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -29,7 +29,6 @@
  *
  * Some parts of System UI maintain a lot of pieces of state at once.
  * [com.android.systemui.plugins.log.LogBuffer] allows us to easily log change events:
- *
  * - 10-10 10:10:10.456: state2 updated to newVal2
  * - 10-10 10:11:00.000: stateN updated to StateN(val1=true, val2=1)
  * - 10-10 10:11:02.123: stateN updated to StateN(val1=true, val2=2)
@@ -37,7 +36,6 @@
  * - 10-10 10:11:06.000: stateN updated to StateN(val1=false, val2=3)
  *
  * However, it can sometimes be more useful to view the state changes in table format:
- *
  * - timestamp--------- | state1- | state2- | ... | stateN.val1 | stateN.val2
  * - -------------------------------------------------------------------------
  * - 10-10 10:10:10.123 | val1--- | val2--- | ... | false------ | 0-----------
@@ -56,23 +54,18 @@
  * individual fields.
  *
  * How it works:
- *
  * 1) Create an instance of this buffer via [TableLogBufferFactory].
- *
  * 2) For any states being logged, implement [Diffable]. Implementing [Diffable] allows the state to
- * only log the fields that have *changed* since the previous update, instead of always logging all
- * fields.
- *
+ *    only log the fields that have *changed* since the previous update, instead of always logging
+ *    all fields.
  * 3) Each time a change in a state happens, call [logDiffs]. If your state is emitted using a
- * [Flow], you should use the [logDiffsForTable] extension function to automatically log diffs any
- * time your flow emits a new value.
+ *    [Flow], you should use the [logDiffsForTable] extension function to automatically log diffs
+ *    any time your flow emits a new value.
  *
  * When a dump occurs, there will be two dumps:
- *
  * 1) The change events under the dumpable name "$name-changes".
- *
  * 2) This class will coalesce all the diffs into a table format and log them under the dumpable
- * name "$name-table".
+ *    name "$name-table".
  *
  * @param maxSize the maximum size of the buffer. Must be > 0.
  */
@@ -99,11 +92,10 @@
      * The [newVal] object's method [Diffable.logDiffs] will be used to fetch the diffs.
      *
      * @param columnPrefix a prefix that will be applied to every column name that gets logged. This
-     * ensures that all the columns related to the same state object will be grouped together in the
-     * table.
-     *
+     *   ensures that all the columns related to the same state object will be grouped together in
+     *   the table.
      * @throws IllegalArgumentException if [columnPrefix] or column name contain "|". "|" is used as
-     * the separator token for parsing, so it can't be present in any part of the column name.
+     *   the separator token for parsing, so it can't be present in any part of the column name.
      */
     @Synchronized
     fun <T : Diffable<T>> logDiffs(columnPrefix: String, prevVal: T, newVal: T) {
@@ -117,7 +109,7 @@
      * Logs change(s) to the buffer using [rowInitializer].
      *
      * @param rowInitializer a function that will be called immediately to store relevant data on
-     * the row.
+     *   the row.
      */
     @Synchronized
     fun logChange(columnPrefix: String, rowInitializer: (TableRowLogger) -> Unit) {
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index 7ccc43c..06668d3 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -38,7 +38,6 @@
      *
      * @param name a unique table name
      * @param maxSize the buffer max size. See [adjustMaxSize]
-     *
      * @return a new [TableLogBuffer] registered with [DumpManager]
      */
     fun create(
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 a057c9f..2509f21 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
@@ -187,6 +187,7 @@
 
     /**
      * Handle request to change the current position in the media track.
+     *
      * @param position Place to seek to in the track.
      */
     @AnyThread
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 0b57175..ae03f27 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
@@ -52,6 +52,7 @@
      * Indicates if all the data is valid.
      *
      * TODO(b/230333302): Make MediaControlPanel more flexible so that we can display fewer than
+     *
      * ```
      *     [NUM_REQUIRED_RECOMMENDATIONS].
      * ```
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 97717a6..207df6b 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
@@ -329,9 +329,8 @@
      * Return the time since last active for the most-recent media.
      *
      * @param sortedEntries userEntries sorted from the earliest to the most-recent.
-     *
      * @return The duration in milliseconds from the most-recent media's last active timestamp to
-     * the present. MAX_VALUE will be returned if there is no media.
+     *   the present. MAX_VALUE will be returned if there is no media.
      */
     private fun timeSinceActiveForMostRecentMedia(
         sortedEntries: SortedMap<String, MediaData>
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 af60e0e..72c4aab 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
@@ -526,8 +526,8 @@
      * through the internal listener pipeline.
      *
      * @param immediately indicates should apply the UI changes immediately, otherwise wait until
-     * the next refresh-round before UI becomes visible. Should only be true if the update is
-     * initiated by user's interaction.
+     *   the next refresh-round before UI becomes visible. Should only be true if the update is
+     *   initiated by user's interaction.
      */
     private fun notifySmartspaceMediaDataRemoved(key: String, immediately: Boolean) {
         internalListeners.forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
@@ -536,6 +536,7 @@
     /**
      * Called whenever the player has been paused or stopped for a while, or swiped from QQS. This
      * will make the player not active anymore, hiding it from QQS and Keyguard.
+     *
      * @see MediaData.active
      */
     internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) {
@@ -1024,6 +1025,7 @@
      * @param packageName Package name for the media app
      * @param controller MediaController for the current session
      * @return a Pair consisting of a list of media actions, and a list of ints representing which
+     *
      * ```
      *      of those actions should be shown in the compact player
      * ```
@@ -1127,6 +1129,7 @@
      *      [PlaybackState.ACTION_SKIP_TO_NEXT]
      * @return
      * ```
+     *
      * A [MediaAction] with correct values set, or null if the state doesn't support it
      */
     private fun getStandardAction(
@@ -1229,6 +1232,7 @@
     }
     /**
      * Load a bitmap from a URI
+     *
      * @param uri the uri to load
      * @return bitmap, or null if couldn't be loaded
      */
@@ -1342,10 +1346,13 @@
     fun onNotificationRemoved(key: String) {
         Assert.isMainThread()
         val removed = mediaEntries.remove(key) ?: return
-
+        val isEligibleForResume =
+            removed.isLocalSession() ||
+                (mediaFlags.isRemoteResumeAllowed() &&
+                    removed.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
         if (keyguardUpdateMonitor.isUserInLockdown(removed.userId)) {
             logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId)
-        } else if (useMediaResumption && removed.resumeAction != null && removed.isLocalSession()) {
+        } else if (useMediaResumption && removed.resumeAction != null && isEligibleForResume) {
             convertToResumePlayer(key, removed)
         } else if (mediaFlags.isRetainingPlayersEnabled()) {
             handlePossibleRemoval(key, removed, notificationRemoved = true)
@@ -1519,15 +1526,13 @@
          * notification key) or vice versa.
          *
          * @param immediately indicates should apply the UI changes immediately, otherwise wait
-         * until the next refresh-round before UI becomes visible. True by default to take in place
-         * immediately.
-         *
+         *   until the next refresh-round before UI becomes visible. True by default to take in
+         *   place immediately.
          * @param receivedSmartspaceCardLatency is the latency between headphone connects and sysUI
-         * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace
-         * signal.
-         *
+         *   displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace
+         *   signal.
          * @param isSsReactivated indicates resume media card is reactivated by Smartspace
-         * recommendation signal
+         *   recommendation signal
          */
         fun onMediaDataLoaded(
             key: String,
@@ -1542,8 +1547,8 @@
          * Called whenever there's new Smartspace media data loaded.
          *
          * @param shouldPrioritize indicates the sorting priority of the Smartspace card. If true,
-         * it will be prioritized as the first card. Otherwise, it will show up as the last card as
-         * default.
+         *   it will be prioritized as the first card. Otherwise, it will show up as the last card
+         *   as default.
          */
         fun onSmartspaceMediaDataLoaded(
             key: String,
@@ -1558,8 +1563,8 @@
          * Called whenever a previously existing Smartspace media data was removed.
          *
          * @param immediately indicates should apply the UI changes immediately, otherwise wait
-         * until the next refresh-round before UI becomes visible. True by default to take in place
-         * immediately.
+         *   until the next refresh-round before UI becomes visible. True by default to take in
+         *   place immediately.
          */
         fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean = true) {}
     }
@@ -1568,7 +1573,7 @@
      * 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.
+     *   SmartspaceTarget's data is invalid.
      */
     private fun toSmartspaceMediaData(target: SmartspaceTarget): SmartspaceMediaData {
         var dismissIntent: Intent? = null
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
index 6a512be..120704c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
@@ -408,9 +408,9 @@
  * [LocalMediaManager.DeviceCallback.onAboutToConnectDeviceAdded] for more information.
  *
  * @property fullMediaDevice a full-fledged [MediaDevice] object representing the device. If
- * non-null, prefer using [fullMediaDevice] over [backupMediaDeviceData].
+ *   non-null, prefer using [fullMediaDevice] over [backupMediaDeviceData].
  * @property backupMediaDeviceData a backup [MediaDeviceData] object containing the minimum
- * information required to display the device. Only use if [fullMediaDevice] is null.
+ *   information required to display the device. Only use if [fullMediaDevice] is null.
  */
 private data class AboutToConnectDevice(
     val fullMediaDevice: MediaDevice? = null,
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 878962d..a1d9214 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
@@ -60,6 +60,7 @@
 
     /**
      * Callback representing that a media object is now expired:
+     *
      * @param key Media control unique identifier
      * @param timedOut True when expired for {@code PAUSED_MEDIA_TIMEOUT} for active media,
      * ```
@@ -70,6 +71,7 @@
 
     /**
      * Callback representing that a media object [PlaybackState] has changed.
+     *
      * @param key Media control unique identifier
      * @param state The new [PlaybackState]
      */
@@ -77,6 +79,7 @@
 
     /**
      * Callback representing that the [MediaSession] for an active control has been destroyed
+     *
      * @param key Media control unique identifier
      */
     lateinit var sessionCallback: (String) -> Unit
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
index 2d10b82..92e0c85 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/MediaResumeListener.kt
@@ -37,6 +37,7 @@
 import com.android.systemui.media.controls.models.player.MediaData
 import com.android.systemui.media.controls.pipeline.MediaDataManager
 import com.android.systemui.media.controls.pipeline.RESUME_MEDIA_TIMEOUT
+import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.tuner.TunerService
 import com.android.systemui.util.Utils
@@ -63,7 +64,8 @@
     private val tunerService: TunerService,
     private val mediaBrowserFactory: ResumeMediaBrowserFactory,
     dumpManager: DumpManager,
-    private val systemClock: SystemClock
+    private val systemClock: SystemClock,
+    private val mediaFlags: MediaFlags,
 ) : MediaDataManager.Listener, Dumpable {
 
     private var useMediaResumption: Boolean = Utils.useMediaResumption(context)
@@ -231,7 +233,11 @@
                 mediaBrowser = null
             }
             // If we don't have a resume action, check if we haven't already
-            if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession()) {
+            val isEligibleForResume =
+                data.isLocalSession() ||
+                    (mediaFlags.isRemoteResumeAllowed() &&
+                        data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE)
+            if (data.resumeAction == null && !data.hasCheckedForResume && isEligibleForResume) {
                 // TODO also check for a media button receiver intended for restarting (b/154127084)
                 Log.d(TAG, "Checking for service component for " + data.packageName)
                 val pm = context.packageManager
@@ -291,6 +297,7 @@
     /**
      * Add the component to the saved list of media browser services, checking for duplicates and
      * removing older components that exceed the maximum limit
+     *
      * @param componentName
      */
     private fun updateResumptionList(componentName: ComponentName) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
index 335ce1d..095cf09 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
@@ -52,10 +52,12 @@
      * event.
      *
      * @param isBrowserConnected true if there's a currently connected
+     *
      * ```
      *     [android.media.browse.MediaBrowser] and false otherwise.
      * @param componentName
      * ```
+     *
      * the component name for the [ResumeMediaBrowser] that triggered this log.
      */
     fun logSessionDestroyed(isBrowserConnected: Boolean, componentName: ComponentName) =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
index d2793bc..f5cc043 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/AnimationBindHandler.kt
@@ -24,10 +24,12 @@
  * and conflicts due to media notifications arriving at any time during an animation. It does this
  * in two parts.
  * - Exit animations fired as a result of user input are tracked. When these are running, any
+ *
  * ```
  *      bind actions are delayed until the animation completes (and then fired in sequence).
  * ```
  * - Continuous animations are tracked using their rebind id. Later calls using the same
+ *
  * ```
  *      rebind id will be totally ignored to prevent the continuous animation from restarting.
  * ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
index 4827a16..2b42604 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/ColorSchemeTransition.kt
@@ -201,7 +201,9 @@
         animatingColorTransitionFactory(
             loadDefaultColor(R.attr.textColorSecondary),
             ::textSecondaryFromScheme
-        ) { textSecondary -> mediaViewHolder.artistText.setTextColor(textSecondary) }
+        ) { textSecondary ->
+            mediaViewHolder.artistText.setTextColor(textSecondary)
+        }
 
     val textTertiary =
         animatingColorTransitionFactory(
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
index 9f86cd8..3669493 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/IlluminationDrawable.kt
@@ -159,6 +159,7 @@
 
     /**
      * Cross fade background.
+     *
      * @see setTintList
      * @see backgroundColor
      */
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 6cf051a..680a8b6 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
@@ -853,10 +853,12 @@
      * @param startLocation the start location of our state or -1 if this is directly set
      * @param endLocation the ending location of our state.
      * @param progress the progress of the transition between startLocation and endlocation. If
+     *
      * ```
      *                 this is not a guided transformation, this will be 1.0f
      * @param immediately
      * ```
+     *
      * should this state be applied immediately, canceling all animations?
      */
     fun setCurrentState(
@@ -1100,17 +1102,17 @@
      *
      * @param eventId UI event id (e.g. 800 for SMARTSPACE_CARD_SEEN)
      * @param instanceId id to uniquely identify a card, e.g. each headphone generates a new
-     * instanceId
+     *   instanceId
      * @param uid uid for the application that media comes from
      * @param surfaces list of display surfaces the media card is on (e.g. lockscreen, shade) when
-     * the event happened
+     *   the event happened
      * @param interactedSubcardRank the rank for interacted media item for recommendation card, -1
-     * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
+     *   for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
      * @param interactedSubcardCardinality how many media items were shown to the user when there is
-     * user interaction
+     *   user interaction
      * @param rank the rank for media card in the media carousel, starting from 0
      * @param receivedLatencyMillis latency in milliseconds for card received events. E.g. latency
-     * between headphone connection to sysUI displays media recommendation card
+     *   between headphone connection to sysUI displays media recommendation card
      * @param isSwipeToDismiss whether is to log swipe-to-dismiss event
      */
     fun logSmartspaceCardReported(
@@ -1371,6 +1373,7 @@
 
     /**
      * Removes media player given the key.
+     *
      * @param isDismissed determines whether the media player is removed from the carousel.
      */
     fun removeMediaPlayer(key: String, isDismissed: Boolean = false) =
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
index 66f12d6..7fc7bdb 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHierarchyManager.kt
@@ -28,7 +28,6 @@
 import android.os.Handler
 import android.os.UserHandle
 import android.provider.Settings
-import android.util.Log
 import android.util.MathUtils
 import android.view.View
 import android.view.ViewGroup
@@ -418,8 +417,8 @@
      * Calculate the alpha of the view when given a cross-fade progress.
      *
      * @param crossFadeProgress The current cross fade progress. 0.5f means it's just switching
-     * between the start and the end location and the content is fully faded, while 0.75f means that
-     * we're halfway faded in again in the target state.
+     *   between the start and the end location and the content is fully faded, while 0.75f means
+     *   that we're halfway faded in again in the target state.
      */
     private fun calculateAlphaFromCrossFade(crossFadeProgress: Float): Float {
         if (crossFadeProgress <= 0.5f) {
@@ -629,6 +628,7 @@
      *
      * @param forceNoAnimation optional parameter telling the system not to animate
      * @param forceStateUpdate optional parameter telling the system to update transition state
+     *
      * ```
      *                         even if location did not change
      * ```
@@ -944,7 +944,7 @@
 
     /**
      * @return the current transformation progress if we're in a guided transformation and -1
-     * otherwise
+     *   otherwise
      */
     private fun getTransformationProgress(): Float {
         if (skipQqsOnExpansion) {
@@ -1055,17 +1055,6 @@
                     // This will either do a full layout pass and remeasure, or it will bypass
                     // that and directly set the mediaFrame's bounds within the premeasured host.
                     targetHost.addView(mediaFrame)
-
-                    if (mediaFrame.childCount > 0) {
-                        val child = mediaFrame.getChildAt(0)
-                        if (mediaFrame.height < child.height) {
-                            Log.wtf(
-                                TAG,
-                                "mediaFrame height is too small for child: " +
-                                    "${mediaFrame.height} vs ${child.height}"
-                            )
-                        }
-                    }
                 }
                 if (isCrossFadeAnimatorRunning) {
                     // When cross-fading with an animation, we only notify the media carousel of the
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
index 455b7de..be570b4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaHost.kt
@@ -126,6 +126,7 @@
      * remeasurings later on.
      *
      * @param location the location this host name has. Used to identify the host during
+     *
      * ```
      *                 transitions.
      * ```
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
index b9b0459..0788e61 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewController.kt
@@ -348,14 +348,17 @@
      * bottom of UMO reach the bottom of this group It will change to alpha 1.0 when the visible
      * bottom of UMO reach the top of the group below e.g.Album title, artist title and play-pause
      * button will change alpha together.
+     *
      * ```
      *     And their alpha becomes 1.0 when the visible bottom of UMO reach the top of controls,
      *     including progress bar, next button, previous button
      * ```
+     *
      * widgetGroupIds: a group of widgets have same state during UMO is squished,
      * ```
      *     e.g. Album title, artist title and play-pause button
      * ```
+     *
      * groupEndPosition: the height of UMO, when the height reaches this value,
      * ```
      *     widgets in this group should have 1.0 as alpha
@@ -363,6 +366,7 @@
      *         visible when the height of UMO reaches the top of controls group
      *         (progress bar, previous button and next button)
      * ```
+     *
      * squishedViewState: hold the widgetState of each widget, which will be modified
      * squishFraction: the squishFraction of UMO
      */
@@ -665,7 +669,7 @@
      *
      * @param location Target
      * @param locationWhenHidden Location that will be used when the target is not
-     * [MediaHost.visible]
+     *   [MediaHost.visible]
      * @return State require for executing a transition, and also the respective [MediaHost].
      */
     private fun obtainViewStateForLocation(@MediaLocation location: Int): TransitionViewState? {
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 c3fa76e..9bc66f6 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
@@ -61,4 +61,7 @@
 
     /** If true, do not automatically dismiss the recommendation card */
     fun isPersistentSsCardEnabled() = featureFlags.isEnabled(Flags.MEDIA_RETAIN_RECOMMENDATIONS)
+
+    /** Check whether we allow remote media to generate resume controls */
+    fun isRemoteResumeAllowed() = featureFlags.isEnabled(Flags.MEDIA_REMOTE_RESUME)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
index e35575b..b5b1f0f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputSwitcherDialogUI.java
@@ -23,8 +23,6 @@
 
 import com.android.systemui.CoreStartable;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.statusbar.CommandQueue;
 
 import javax.inject.Inject;
@@ -37,26 +35,19 @@
 
     private final CommandQueue mCommandQueue;
     private final MediaOutputDialogFactory mMediaOutputDialogFactory;
-    private final FeatureFlags mFeatureFlags;
 
     @Inject
     public MediaOutputSwitcherDialogUI(
             Context context,
             CommandQueue commandQueue,
-            MediaOutputDialogFactory mediaOutputDialogFactory,
-            FeatureFlags featureFlags) {
+            MediaOutputDialogFactory mediaOutputDialogFactory) {
         mCommandQueue = commandQueue;
         mMediaOutputDialogFactory = mediaOutputDialogFactory;
-        mFeatureFlags = featureFlags;
     }
 
     @Override
     public void start() {
-        if (mFeatureFlags.isEnabled(Flags.OUTPUT_SWITCHER_SHOW_API_ENABLED)) {
-            mCommandQueue.addCallback(this);
-        } else {
-            Log.w(TAG, "Show media output switcher is not enabled.");
-        }
+        mCommandQueue.addCallback(this);
     }
 
     @Override
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 720c44a..ee93c37 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
@@ -43,7 +43,7 @@
          *
          * @param appPackageName the package name of the app playing the media.
          * @param onPackageNotFoundException a function run if a
-         * [PackageManager.NameNotFoundException] occurs.
+         *   [PackageManager.NameNotFoundException] occurs.
          * @param isReceiver indicates whether the icon is displayed in a receiver view.
          */
         fun getIconInfoFromPackageName(
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
index 7a77c47..01398cf 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt
@@ -70,6 +70,8 @@
                 RECENT_IGNORE_UNAVAILABLE,
                 userTracker.userId,
                 backgroundExecutor
-            ) { tasks -> continuation.resume(tasks) }
+            ) { tasks ->
+                continuation.resume(tasks)
+            }
         }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
index d4991f9..9b9d561 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/MediaProjectionTaskView.kt
@@ -33,7 +33,7 @@
 import com.android.systemui.mediaprojection.appselector.data.RecentTask
 import com.android.systemui.shared.recents.model.ThumbnailData
 import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
-import com.android.systemui.shared.recents.utilities.Utilities.isTablet
+import com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen
 
 /**
  * Custom view that shows a thumbnail preview of one recent task based on [ThumbnailData].
@@ -150,9 +150,9 @@
         val displayWidthPx = windowMetrics.bounds.width()
         val displayHeightPx = windowMetrics.bounds.height()
         val isRtl = layoutDirection == LAYOUT_DIRECTION_RTL
-        val isTablet = isTablet(context)
+        val isLargeScreen = isLargeScreen(context)
         val taskbarSize =
-            if (isTablet) {
+            if (isLargeScreen) {
                 resources.getDimensionPixelSize(AndroidR.dimen.taskbar_frame_height)
             } else {
                 0
@@ -166,7 +166,7 @@
             displayWidthPx,
             displayHeightPx,
             taskbarSize,
-            isTablet,
+            isLargeScreen,
             currentRotation,
             isRtl
         )
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
index 88d5eaa..1c90154 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/TaskPreviewSizeProvider.kt
@@ -23,7 +23,7 @@
 import com.android.internal.R as AndroidR
 import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorScope
 import com.android.systemui.mediaprojection.appselector.view.TaskPreviewSizeProvider.TaskPreviewSizeListener
-import com.android.systemui.shared.recents.utilities.Utilities.isTablet
+import com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen
 import com.android.systemui.statusbar.policy.CallbackController
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
@@ -61,8 +61,8 @@
         val width = windowMetrics.bounds.width()
         var height = maximumWindowHeight
 
-        val isTablet = isTablet(context)
-        if (isTablet) {
+        val isLargeScreen = isLargeScreen(context)
+        if (isLargeScreen) {
             val taskbarSize =
                 context.resources.getDimensionPixelSize(AndroidR.dimen.taskbar_frame_height)
             height -= taskbarSize
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index d5d7325..4db1da3 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -41,7 +41,7 @@
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS;
 import static com.android.systemui.navigationbar.NavBarHelper.transitionMode;
 import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
-import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
+import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
@@ -1792,7 +1792,7 @@
 
     private void setNavigationIconHints(int hints) {
         if (hints == mNavigationIconHints) return;
-        if (!isTablet(mContext)) {
+        if (!isLargeScreen(mContext)) {
             // All IME functions handled by launcher via Sysui flags for large screen
             final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
             final boolean oldBackAlt =
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 3c17465..63d977e 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -21,7 +21,7 @@
 import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR;
 
 import static com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler.DEBUG_MISSING_GESTURE_TAG;
-import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
+import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
 
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -91,7 +91,7 @@
     private final DisplayManager mDisplayManager;
     private final TaskbarDelegate mTaskbarDelegate;
     private int mNavMode;
-    @VisibleForTesting boolean mIsTablet;
+    @VisibleForTesting boolean mIsLargeScreen;
 
     /** A displayId - nav bar maps. */
     @VisibleForTesting
@@ -138,16 +138,16 @@
                 navBarHelper, navigationModeController, sysUiFlagsContainer,
                 dumpManager, autoHideController, lightBarController, pipOptional,
                 backAnimation.orElse(null), taskStackChangeListeners);
-        mIsTablet = isTablet(mContext);
+        mIsLargeScreen = isLargeScreen(mContext);
         dumpManager.registerDumpable(this);
     }
 
     @Override
     public void onConfigChanged(Configuration newConfig) {
-        boolean isOldConfigTablet = mIsTablet;
-        mIsTablet = isTablet(mContext);
+        boolean isOldConfigLargeScreen = mIsLargeScreen;
+        mIsLargeScreen = isLargeScreen(mContext);
         boolean willApplyConfig = mConfigChanges.applyNewConfig(mContext.getResources());
-        boolean largeScreenChanged = mIsTablet != isOldConfigTablet;
+        boolean largeScreenChanged = mIsLargeScreen != isOldConfigLargeScreen;
         // TODO(b/243765256): Disable this logging once b/243765256 is fixed.
         Log.i(DEBUG_MISSING_GESTURE_TAG, "NavbarController: newConfig=" + newConfig
                 + " mTaskbarDelegate initialized=" + mTaskbarDelegate.isInitialized()
@@ -235,8 +235,9 @@
 
     /** @return {@code true} if taskbar is enabled, false otherwise */
     private boolean initializeTaskbarIfNecessary() {
-        // Enable for tablet or (phone AND flag is set); assuming phone = !mIsTablet
-        boolean taskbarEnabled = mIsTablet || mFeatureFlags.isEnabled(Flags.HIDE_NAVBAR_WINDOW);
+        // Enable for large screens or (phone AND flag is set); assuming phone = !mIsLargeScreen
+        boolean taskbarEnabled = mIsLargeScreen || mFeatureFlags.isEnabled(
+                Flags.HIDE_NAVBAR_WINDOW);
 
         if (taskbarEnabled) {
             Trace.beginSection("NavigationBarController#initializeTaskbarIfNecessary");
@@ -258,7 +259,7 @@
     @Override
     public void onDisplayReady(int displayId) {
         Display display = mDisplayManager.getDisplay(displayId);
-        mIsTablet = isTablet(mContext);
+        mIsLargeScreen = isLargeScreen(mContext);
         createNavigationBar(display, null /* savedState */, null /* result */);
     }
 
@@ -470,7 +471,7 @@
 
     @Override
     public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
-        pw.println("mIsTablet=" + mIsTablet);
+        pw.println("mIsLargeScreen=" + mIsLargeScreen);
         pw.println("mNavMode=" + mNavMode);
         for (int i = 0; i < mNavigationBars.size(); i++) {
             if (i > 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index f3d6014..342e0b00 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -234,6 +234,7 @@
     private boolean mLogGesture = false;
     private boolean mInRejectedExclusion = false;
     private boolean mIsOnLeftEdge;
+    private boolean mDeferSetIsOnLeftEdge;
 
     private boolean mIsAttached;
     private boolean mIsGesturalModeEnabled;
@@ -878,7 +879,9 @@
             // either the bouncer is showing or the notification panel is hidden
             mInputEventReceiver.setBatchingEnabled(false);
             if (isTrackpadEvent) {
-                // TODO: show the back arrow based on the direction of the swipe.
+                // Since trackpad gestures don't have zones, this will be determined later by the
+                // direction of the gesture. {@code mIsOnLeftEdge} is set to false to begin with.
+                mDeferSetIsOnLeftEdge = true;
                 mIsOnLeftEdge = false;
             } else {
                 mIsOnLeftEdge = ev.getX() <= mEdgeWidthLeft + mLeftInset;
@@ -899,7 +902,7 @@
                 mEdgeBackPlugin.onMotionEvent(ev);
                 dispatchToBackAnimation(ev);
             }
-            if (mLogGesture) {
+            if (mLogGesture || isTrackpadEvent) {
                 mDownPoint.set(ev.getX(), ev.getY());
                 mEndPoint.set(-1, -1);
                 mThresholdCrossed = false;
@@ -907,9 +910,9 @@
 
             // For debugging purposes, only log edge points
             (isWithinInsets ? mGestureLogInsideInsets : mGestureLogOutsideInsets).log(String.format(
-                    "Gesture [%d,alw=%B,%B,%B,%B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
+                    "Gesture [%d,alw=%B,%B,%B,%B,%B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
                     System.currentTimeMillis(), isTrackpadEvent, mAllowGesture, mIsOnLeftEdge,
-                    mIsBackGestureAllowed,
+                    mDeferSetIsOnLeftEdge, mIsBackGestureAllowed,
                     QuickStepContract.isBackGestureDisabled(mSysUiFlags), mDisplaySize,
                     mEdgeWidthLeft, mLeftInset, mEdgeWidthRight, mRightInset, mExcludeRegion));
         } else if (mAllowGesture || mLogGesture) {
@@ -928,6 +931,14 @@
                     mLogGesture = false;
                     return;
                 } else if (action == MotionEvent.ACTION_MOVE) {
+                    if (isTrackpadEvent && mDeferSetIsOnLeftEdge) {
+                        // mIsOnLeftEdge is determined by the relative position between the down
+                        // and the current motion event for trackpad gestures instead of zoning.
+                        mIsOnLeftEdge = mEndPoint.x > mDownPoint.x;
+                        mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
+                        mDeferSetIsOnLeftEdge = false;
+                    }
+
                     if ((ev.getEventTime() - ev.getDownTime()) > mLongPressTimeout) {
                         if (mAllowGesture) {
                             logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_LONG_PRESS);
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index be615d6..c65f0aa 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -17,20 +17,26 @@
 package com.android.systemui.notetask
 
 import android.app.KeyguardManager
+import android.app.admin.DevicePolicyManager
 import android.content.ActivityNotFoundException
 import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
 import android.content.pm.PackageManager
+import android.os.Build
 import android.os.UserManager
 import android.util.Log
-import com.android.internal.logging.UiEvent
-import com.android.internal.logging.UiEventLogger
+import androidx.annotation.VisibleForTesting
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
 import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.kotlin.getOrNull
+import com.android.wm.shell.bubbles.Bubble
 import com.android.wm.shell.bubbles.Bubbles
+import com.android.wm.shell.bubbles.Bubbles.BubbleExpandListener
 import java.util.Optional
+import java.util.concurrent.atomic.AtomicReference
 import javax.inject.Inject
 
 /**
@@ -41,18 +47,42 @@
  * Currently, we only support a single task per time.
  */
 @SysUISingleton
-internal class NoteTaskController
+class NoteTaskController
 @Inject
 constructor(
     private val context: Context,
     private val resolver: NoteTaskInfoResolver,
+    private val eventLogger: NoteTaskEventLogger,
     private val optionalBubbles: Optional<Bubbles>,
-    private val optionalKeyguardManager: Optional<KeyguardManager>,
     private val optionalUserManager: Optional<UserManager>,
+    private val optionalKeyguardManager: Optional<KeyguardManager>,
     @NoteTaskEnabledKey private val isEnabled: Boolean,
-    private val uiEventLogger: UiEventLogger,
+    private val devicePolicyManager: DevicePolicyManager,
+    private val userTracker: UserTracker,
 ) {
 
+    @VisibleForTesting val infoReference = AtomicReference<NoteTaskInfo?>()
+
+    /** @see BubbleExpandListener */
+    fun onBubbleExpandChanged(isExpanding: Boolean, key: String?) {
+        if (!isEnabled) return
+
+        if (key != Bubble.KEY_APP_BUBBLE) return
+
+        val info = infoReference.getAndSet(null)
+
+        // Safe guard mechanism, this callback should only be called for app bubbles.
+        if (info?.launchMode != NoteTaskLaunchMode.AppBubble) return
+
+        if (isExpanding) {
+            logDebug { "onBubbleExpandChanged - expanding: $info" }
+            eventLogger.logNoteTaskOpened(info)
+        } else {
+            logDebug { "onBubbleExpandChanged - collapsing: $info" }
+            eventLogger.logNoteTaskClosed(info)
+        }
+    }
+
     /**
      * Shows a note task. How the task is shown will depend on when the method is invoked.
      *
@@ -69,32 +99,62 @@
      * That will let users open other apps in full screen, and take contextual notes.
      */
     @JvmOverloads
-    fun showNoteTask(isInMultiWindowMode: Boolean = false, uiEvent: ShowNoteTaskUiEvent? = null) {
-
+    fun showNoteTask(
+        entryPoint: NoteTaskEntryPoint,
+        isInMultiWindowMode: Boolean = false,
+    ) {
         if (!isEnabled) return
 
         val bubbles = optionalBubbles.getOrNull() ?: return
-        val keyguardManager = optionalKeyguardManager.getOrNull() ?: return
         val userManager = optionalUserManager.getOrNull() ?: return
+        val keyguardManager = optionalKeyguardManager.getOrNull() ?: return
 
         // TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing.
         if (!userManager.isUserUnlocked) return
 
-        val noteTaskInfo = resolver.resolveInfo() ?: return
+        val isKeyguardLocked = keyguardManager.isKeyguardLocked
+        // KeyguardQuickAffordanceInteractor blocks the quick affordance from showing in the
+        // keyguard if it is not allowed by the admin policy. Here we block any other way to show
+        // note task when the screen is locked.
+        if (
+            isKeyguardLocked &&
+                devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
+        ) {
+            logDebug { "Enterprise policy disallows launching note app when the screen is locked." }
+            return
+        }
 
-        uiEvent?.let { uiEventLogger.log(it, noteTaskInfo.uid, noteTaskInfo.packageName) }
+        val info =
+            resolver.resolveInfo(
+                entryPoint = entryPoint,
+                isInMultiWindowMode = isInMultiWindowMode,
+                isKeyguardLocked = isKeyguardLocked,
+            )
+                ?: return
+
+        infoReference.set(info)
 
         // TODO(b/266686199): We should handle when app not available. For now, we log.
-        val intent = noteTaskInfo.toCreateNoteIntent()
+        val intent = createNoteIntent(info)
         try {
-            if (isInMultiWindowMode || keyguardManager.isKeyguardLocked) {
-                context.startActivity(intent)
-            } else {
-                bubbles.showOrHideAppBubble(intent)
+            logDebug { "onShowNoteTask - start: $info" }
+            when (info.launchMode) {
+                is NoteTaskLaunchMode.AppBubble -> {
+                    bubbles.showOrHideAppBubble(intent)
+                    // App bubble logging happens on `onBubbleExpandChanged`.
+                    logDebug { "onShowNoteTask - opened as app bubble: $info" }
+                }
+                is NoteTaskLaunchMode.Activity -> {
+                    context.startActivity(intent)
+                    eventLogger.logNoteTaskOpened(info)
+                    logDebug { "onShowNoteTask - opened as activity: $info" }
+                }
             }
+            logDebug { "onShowNoteTask - success: $info" }
         } catch (e: ActivityNotFoundException) {
-            Log.e(TAG, "Activity not found for action: $ACTION_CREATE_NOTE.", e)
+            logDebug { "onShowNoteTask - failed: $info" }
         }
+        logDebug { "onShowNoteTask - compoleted: $info" }
     }
 
     /**
@@ -119,41 +179,12 @@
             enabledState,
             PackageManager.DONT_KILL_APP,
         )
-    }
 
-    /** 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
+        logDebug { "setNoteTaskShortcutEnabled - completed: $isEnabled" }
     }
 
     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)
-        }
+        val TAG = NoteTaskController::class.simpleName.orEmpty()
 
         // TODO(b/254604589): Use final KeyEvent.KEYCODE_* instead.
         const val NOTE_TASK_KEY_EVENT = 311
@@ -165,3 +196,17 @@
         const val INTENT_EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE"
     }
 }
+
+private fun createNoteIntent(info: NoteTaskInfo): Intent =
+    Intent(NoteTaskController.ACTION_CREATE_NOTE)
+        .setPackage(info.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(NoteTaskController.INTENT_EXTRA_USE_STYLUS_MODE, true)
+
+private inline fun logDebug(message: () -> String) {
+    if (Build.IS_DEBUGGABLE) {
+        Log.d(NoteTaskController.TAG, message())
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt
index e0bf1da..a256391 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt
@@ -19,4 +19,4 @@
 import javax.inject.Qualifier
 
 /** Key associated with a [Boolean] flag that enables or disables the note task feature. */
-@Qualifier internal annotation class NoteTaskEnabledKey
+@Qualifier annotation class NoteTaskEnabledKey
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
new file mode 100644
index 0000000..acc537a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt
@@ -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.notetask
+
+import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceConfig
+import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
+import com.android.systemui.screenshot.AppClipsTrampolineActivity
+
+/**
+ * Supported entry points for [NoteTaskController.showNoteTask].
+ *
+ * An entry point represents where the note task has ben called from. In rare cases, it may
+ * represent a "re-entry" (i.e., [APP_CLIPS]).
+ */
+enum class NoteTaskEntryPoint {
+
+    /** @see [LaunchNoteTaskActivity] */
+    WIDGET_PICKER_SHORTCUT,
+
+    /** @see [NoteTaskQuickAffordanceConfig] */
+    QUICK_AFFORDANCE,
+
+    /** @see [NoteTaskInitializer.callbacks] */
+    TAIL_BUTTON,
+
+    /** @see [AppClipsTrampolineActivity] */
+    APP_CLIPS,
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt
new file mode 100644
index 0000000..16dd16e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.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.notetask
+
+import com.android.internal.logging.UiEvent
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.notetask.NoteTaskEntryPoint.APP_CLIPS
+import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE
+import com.android.systemui.notetask.NoteTaskEntryPoint.TAIL_BUTTON
+import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+import javax.inject.Inject
+
+/**
+ * A wrapper around [UiEventLogger] specialized in the note taking UI events.
+ *
+ * if the accepted [NoteTaskInfo] contains a [NoteTaskInfo.entryPoint], it will be logged as the
+ * correct [NoteTaskUiEvent]. If null, it will be ignored.
+ *
+ * @see NoteTaskController for usage examples.
+ */
+class NoteTaskEventLogger @Inject constructor(private val uiEventLogger: UiEventLogger) {
+
+    /** Logs a [NoteTaskInfo] as an **open** [NoteTaskUiEvent], including package name and uid. */
+    fun logNoteTaskOpened(info: NoteTaskInfo) {
+        val event =
+            when (info.entryPoint) {
+                TAIL_BUTTON -> {
+                    if (info.isKeyguardLocked) {
+                        NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+                    } else {
+                        NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+                    }
+                }
+                WIDGET_PICKER_SHORTCUT -> NOTE_OPENED_VIA_SHORTCUT
+                QUICK_AFFORDANCE -> NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+                APP_CLIPS -> return
+                null -> return
+            }
+        uiEventLogger.log(event, info.uid, info.packageName)
+    }
+
+    /** Logs a [NoteTaskInfo] as a **closed** [NoteTaskUiEvent], including package name and uid. */
+    fun logNoteTaskClosed(info: NoteTaskInfo) {
+        val event =
+            when (info.entryPoint) {
+                TAIL_BUTTON -> {
+                    if (info.isKeyguardLocked) {
+                        NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+                    } else {
+                        NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON
+                    }
+                }
+                WIDGET_PICKER_SHORTCUT -> return
+                QUICK_AFFORDANCE -> return
+                APP_CLIPS -> return
+                null -> return
+            }
+        uiEventLogger.log(event, info.uid, info.packageName)
+    }
+
+    /** IDs of UI events accepted by [NoteTaskController]. */
+    enum class NoteTaskUiEvent(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),
+
+        @UiEvent(doc = "User opened a note by pressing the stylus tail button while the screen was unlocked.") // ktlint-disable max-line-length
+        NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON(1295),
+
+        @UiEvent(doc = "User opened a note by pressing the stylus tail button while the screen was locked.") // ktlint-disable max-line-length
+        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),
+
+        @UiEvent(doc = "Note closed via a tail button while device is unlocked")
+        NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON(1311),
+
+        @UiEvent(doc = "Note closed via a tail button while device is locked")
+        NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1312);
+
+        override fun getId() = _id
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt
new file mode 100644
index 0000000..28d7647
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.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.notetask
+
+/** Contextual information required to launch a Note Task by [NoteTaskController]. */
+data class NoteTaskInfo(
+    val packageName: String,
+    val uid: Int,
+    val entryPoint: NoteTaskEntryPoint? = null,
+    val isInMultiWindowMode: Boolean = false,
+    val isKeyguardLocked: Boolean = false,
+) {
+
+    val launchMode: NoteTaskLaunchMode =
+        if (isInMultiWindowMode || isKeyguardLocked) {
+            NoteTaskLaunchMode.Activity
+        } else {
+            NoteTaskLaunchMode.AppBubble
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
index bd822d4..0f75f95 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfoResolver.kt
@@ -19,51 +19,58 @@
 import android.app.role.RoleManager
 import android.content.Context
 import android.content.pm.PackageManager
+import android.content.pm.PackageManager.ApplicationInfoFlags
 import android.os.UserHandle
 import android.util.Log
 import javax.inject.Inject
 
-internal class NoteTaskInfoResolver
+class NoteTaskInfoResolver
 @Inject
 constructor(
     private val context: Context,
     private val roleManager: RoleManager,
     private val packageManager: PackageManager,
 ) {
-    fun resolveInfo(): NoteTaskInfo? {
+
+    fun resolveInfo(
+        entryPoint: NoteTaskEntryPoint? = null,
+        isInMultiWindowMode: Boolean = false,
+        isKeyguardLocked: Boolean = false,
+    ): 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()
+        val packageName =
+            roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, user).firstOrNull()
 
         if (packageName.isNullOrEmpty()) return null
 
-        return NoteTaskInfo(packageName, packageManager.getUidOf(packageName, user))
+        return NoteTaskInfo(
+            packageName = packageName,
+            uid = packageManager.getUidOf(packageName, user),
+            entryPoint = entryPoint,
+            isInMultiWindowMode = isInMultiWindowMode,
+            isKeyguardLocked = isKeyguardLocked,
+        )
     }
 
-    /** 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)!!
+        // TODO(b/265912743): Use RoleManager.NOTES_ROLE instead.
+        const val ROLE_NOTES = "android.app.role.NOTES"
+
+        private val EMPTY_APPLICATION_INFO_FLAGS = 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"
+        private fun PackageManager.getUidOf(packageName: String, user: UserHandle): Int =
+            try {
+                getApplicationInfoAsUser(packageName, EMPTY_APPLICATION_INFO_FLAGS, user).uid
+            } catch (e: PackageManager.NameNotFoundException) {
+                Log.e(TAG, "Couldn't find notes app UID", e)
+                0
+            }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
index d40bf2b..fb3c0cb 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInitializer.kt
@@ -13,13 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package com.android.systemui.notetask
 
-import android.app.KeyguardManager
+import android.view.KeyEvent
 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
@@ -28,41 +26,28 @@
 internal class NoteTaskInitializer
 @Inject
 constructor(
-    private val optionalBubbles: Optional<Bubbles>,
-    private val noteTaskController: NoteTaskController,
+    private val controller: NoteTaskController,
     private val commandQueue: CommandQueue,
+    private val optionalBubbles: Optional<Bubbles>,
     @NoteTaskEnabledKey private val isEnabled: Boolean,
-    private val optionalKeyguardManager: Optional<KeyguardManager>,
 ) {
 
     @VisibleForTesting
     val callbacks =
         object : CommandQueue.Callbacks {
             override fun handleSystemKey(keyCode: Int) {
-                if (keyCode == NoteTaskController.NOTE_TASK_KEY_EVENT) {
-                    showNoteTask()
+                if (keyCode == KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL) {
+                    controller.showNoteTask(NoteTaskEntryPoint.TAIL_BUTTON)
                 }
             }
         }
 
-    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)
-        }
-        noteTaskController.setNoteTaskShortcutEnabled(isEnabled)
+        controller.setNoteTaskShortcutEnabled(isEnabled)
+
+        // Guard against feature not being enabled or mandatory dependencies aren't available.
+        if (!isEnabled || optionalBubbles.isEmpty) return
+
+        commandQueue.addCallback(callbacks)
     }
 }
-
-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/NoteTaskLaunchMode.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskLaunchMode.kt
new file mode 100644
index 0000000..836e103f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskLaunchMode.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.notetask
+
+import android.content.Context
+import com.android.wm.shell.bubbles.Bubbles
+
+/**
+ * Supported ways for launching a note taking experience.
+ *
+ * @see [NoteTaskController.showNoteTask]
+ */
+sealed class NoteTaskLaunchMode {
+
+    /** @see Bubbles.showOrHideAppBubble */
+    object AppBubble : NoteTaskLaunchMode()
+
+    /** @see Context.startActivity */
+    object Activity : NoteTaskLaunchMode()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
index b8800a2..ba8999c 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
@@ -36,7 +36,7 @@
 
 /** Compose all dependencies required by Note Task feature. */
 @Module(includes = [NoteTaskQuickAffordanceModule::class])
-internal interface NoteTaskModule {
+interface NoteTaskModule {
 
     @[Binds IntoMap ClassKey(LaunchNoteTaskActivity::class)]
     fun LaunchNoteTaskActivity.bindNoteTaskLauncherActivity(): Activity
@@ -51,7 +51,7 @@
             featureFlags: FeatureFlags,
             roleManager: RoleManager,
         ): Boolean {
-            val isRoleAvailable = roleManager.isRoleAvailable(NoteTaskInfoResolver.ROLE_NOTES)
+            val isRoleAvailable = roleManager.isRoleAvailable(RoleManager.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 43869cc..30660c4 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceConfig.kt
@@ -27,12 +27,12 @@
 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 com.android.systemui.notetask.NoteTaskEntryPoint
 import javax.inject.Inject
 import kotlinx.coroutines.flow.flowOf
 
-internal class NoteTaskQuickAffordanceConfig
+class NoteTaskQuickAffordanceConfig
 @Inject
 constructor(
     context: Context,
@@ -66,7 +66,7 @@
 
     override fun onTriggered(expandable: Expandable?): OnTriggeredResult {
         noteTaskController.showNoteTask(
-            uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+            entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE,
         )
         return OnTriggeredResult.Handled
     }
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt
index 7cb932a..2d63dbc 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/quickaffordance/NoteTaskQuickAffordanceModule.kt
@@ -22,7 +22,7 @@
 import dagger.multibindings.IntoSet
 
 @Module
-internal interface NoteTaskQuickAffordanceModule {
+interface NoteTaskQuickAffordanceModule {
 
     @[Binds IntoSet]
     fun NoteTaskQuickAffordanceConfig.bindNoteTaskQuickAffordance(): KeyguardQuickAffordanceConfig
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
index 6ab0da6..8ced4646 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
@@ -33,10 +33,10 @@
  * launched, creating a new shortcut for [CreateNoteTaskShortcutActivity], and will finish.
  *
  * @see <a
- * href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
- * a custom shortcut activity</a>
+ *   href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
+ *   a custom shortcut activity</a>
  */
-internal class CreateNoteTaskShortcutActivity @Inject constructor() : ComponentActivity() {
+class CreateNoteTaskShortcutActivity @Inject constructor() : ComponentActivity() {
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
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 3ac5bfa..80fce6a 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/LaunchNoteTaskActivity.kt
@@ -21,11 +21,11 @@
 import android.os.Bundle
 import androidx.activity.ComponentActivity
 import com.android.systemui.notetask.NoteTaskController
-import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
+import com.android.systemui.notetask.NoteTaskEntryPoint
 import javax.inject.Inject
 
 /** Activity responsible for launching the note experience, and finish. */
-internal class LaunchNoteTaskActivity
+class LaunchNoteTaskActivity
 @Inject
 constructor(
     private val noteTaskController: NoteTaskController,
@@ -35,8 +35,8 @@
         super.onCreate(savedInstanceState)
 
         noteTaskController.showNoteTask(
+            entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT,
             isInMultiWindowMode = isInMultiWindowMode,
-            uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT,
         )
 
         finish()
@@ -49,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 = NoteTaskController.ACTION_CREATE_NOTE
+                action = Intent.ACTION_CREATE_NOTE
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
index ff3ec72..d40112f 100644
--- a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
@@ -26,8 +26,7 @@
 @Module
 interface QRCodeScannerModule {
 
-    /**
-     */
+    /**  */
     @Binds
     @IntoMap
     @StringKey(QRCodeScannerTile.TILE_SPEC)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index e86bd7a..9f93e49 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -76,7 +76,8 @@
         this(tileServices, handler, userTracker, new TileLifecycleManager(handler,
                 tileServices.getContext(), tileServices,
                 new PackageManagerAdapter(tileServices.getContext()), broadcastDispatcher,
-                new Intent().setComponent(component), userTracker.getUserHandle()));
+                new Intent(TileService.ACTION_QS_TILE).setComponent(component),
+                userTracker.getUserHandle()));
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
index 03bb7a0..8387c1d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt
@@ -71,8 +71,8 @@
     /**
      * Show the device monitoring dialog, expanded from [expandable] if it's not null.
      *
-     * Important: [quickSettingsContext] *must* be the [Context] associated to the [Quick Settings
-     * fragment][com.android.systemui.qs.QSFragment].
+     * Important: [quickSettingsContext] *must* be the [Context] associated to the
+     * [Quick Settings fragment][com.android.systemui.qs.QSFragment].
      */
     fun showDeviceMonitoringDialog(quickSettingsContext: Context, expandable: Expandable?)
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
index fbf32b3..f170ac1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt
@@ -196,9 +196,9 @@
      * Observe the device monitoring dialog requests and show the dialog accordingly. This function
      * will suspend indefinitely and will need to be cancelled to stop observing.
      *
-     * Important: [quickSettingsContext] must be the [Context] associated to the [Quick Settings
-     * fragment][com.android.systemui.qs.QSFragment], and the call to this function must be
-     * cancelled when that fragment is destroyed.
+     * Important: [quickSettingsContext] must be the [Context] associated to the
+     * [Quick Settings fragment][com.android.systemui.qs.QSFragment], and the call to this function
+     * must be cancelled when that fragment is destroyed.
      */
     suspend fun observeDeviceMonitoringDialogRequests(quickSettingsContext: Context) {
         footerActionsInteractor.deviceMonitoringDialogRequests.collect {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 645b125..346acf9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.recents;
 
-import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
+import static com.android.systemui.shared.recents.utilities.Utilities.isLargeScreen;
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
@@ -265,7 +265,7 @@
                     .setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
             View buttons = mLayout.findViewById(R.id.screen_pinning_buttons);
             if (!QuickStepContract.isGesturalMode(mNavBarMode)
-            	    && hasSoftNavigationBar(mContext.getDisplayId()) && !isTablet(mContext)) {
+            	    && hasSoftNavigationBar(mContext.getDisplayId()) && !isLargeScreen(mContext)) {
                 buttons.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
                 swapChildrenIfRtlAndVertical(buttons);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index dd21be9..30509e2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -124,8 +124,9 @@
 
     /**
      * Starts screen capture after some countdown
+     *
      * @param captureTarget target to capture (could be e.g. a task) or null to record the whole
-     * screen
+     *   screen
      */
     private fun requestScreenCapture(captureTarget: MediaProjectionCaptureTarget?) {
         val userContext = userContextProvider.userContext
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
index 310baaf..a8f99be 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentCreator.kt
@@ -70,7 +70,7 @@
 
     /**
      * @return an ACTION_EDIT intent for the given URI, directed to config_screenshotEditor if
-     * available.
+     *   available.
      */
     fun createEditIntent(uri: Uri, context: Context): Intent {
         val editIntent = Intent(Intent.ACTION_EDIT)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
index 1b728b8..236213c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/WorkProfileMessageController.kt
@@ -44,7 +44,7 @@
 
     /**
      * @return a populated WorkProfileFirstRunData object if a work profile first run message should
-     * be shown
+     *   be shown
      */
     fun onScreenshotTaken(userHandle: UserHandle?): WorkProfileFirstRunData? {
         if (userHandle == null) return 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
index 1946b8e..eda38e4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
@@ -50,6 +50,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.notetask.NoteTaskController;
+import com.android.systemui.notetask.NoteTaskEntryPoint;
 import com.android.systemui.settings.UserTracker;
 import com.android.wm.shell.bubbles.Bubbles;
 
@@ -239,9 +240,8 @@
             // 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);
+            // Expand the note bubble before returning the result.
+            mNoteTaskController.showNoteTask(NoteTaskEntryPoint.APP_CLIPS);
             setResult(RESULT_OK, convertedData);
             finish();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
index b36f0d7..10e2afe 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimDrawable.java
@@ -27,6 +27,7 @@
 import android.graphics.Path;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.graphics.Xfermode;
 import android.graphics.drawable.Drawable;
 import android.view.animation.DecelerateInterpolator;
@@ -41,7 +42,11 @@
 public class ScrimDrawable extends Drawable {
     private static final String TAG = "ScrimDrawable";
 
+    private boolean mShouldUseLargeScreenSize;
     private final Paint mPaint;
+    private final Path mPath = new Path();
+    private final RectF mBoundsRectF = new RectF();
+
     private int mAlpha = 255;
     private int mMainColor;
     private ValueAnimator mColorAnimation;
@@ -49,11 +54,13 @@
     private float mCornerRadius;
     private ConcaveInfo mConcaveInfo;
     private int mBottomEdgePosition;
+    private float mBottomEdgeRadius = -1;
     private boolean mCornerRadiusEnabled;
 
     public ScrimDrawable() {
         mPaint = new Paint();
         mPaint.setStyle(Paint.Style.FILL);
+        mShouldUseLargeScreenSize = false;
     }
 
     /**
@@ -133,6 +140,10 @@
         return PixelFormat.TRANSLUCENT;
     }
 
+    public void setShouldUseLargeScreenSize(boolean v) {
+        mShouldUseLargeScreenSize = v;
+    }
+
     /**
      * Corner radius used by either concave or convex corners.
      */
@@ -191,6 +202,10 @@
         invalidateSelf();
     }
 
+    public void setBottomEdgeRadius(float radius) {
+        mBottomEdgeRadius = radius;
+    }
+
     @Override
     public void draw(@NonNull Canvas canvas) {
         mPaint.setColor(mMainColor);
@@ -198,9 +213,46 @@
         if (mConcaveInfo != null) {
             drawConcave(canvas);
         } else if (mCornerRadiusEnabled && mCornerRadius > 0) {
-            canvas.drawRoundRect(getBounds().left, getBounds().top, getBounds().right,
-                    getBounds().bottom,
-                    /* x radius*/ mCornerRadius, /* y radius*/ mCornerRadius, mPaint);
+            float topEdgeRadius = mCornerRadius;
+            float bottomEdgeRadius = mBottomEdgeRadius == -1.0 ? mCornerRadius : mBottomEdgeRadius;
+
+            mBoundsRectF.set(getBounds());
+
+            // When the back gesture causes the notification scrim to be scaled down,
+            // this offset "reveals" the rounded bottom edge as it "pulls away".
+            // We must *not* make this adjustment on largescreen shades (where the corner is sharp).
+            if (!mShouldUseLargeScreenSize && mBottomEdgeRadius != -1) {
+                mBoundsRectF.bottom -= bottomEdgeRadius;
+            }
+
+            // We need a box with rounded corners but its lower corners are not rounded on large
+            // screen devices in "portrait" orientation.
+            // Thus, we cannot draw a symmetric rounded rectangle via canvas.drawRoundRect()
+            // and must build a box with different corner radii at the top and at the bottom.
+            // Additionally, when the scrim is pushed to the very bottom of the screen, do not draw
+            // anything (drawing a rounded box with these specifications is not possible).
+            // TODO(b/271030611) perhaps this could be accomplished via Path.addRoundRect instead?
+            if (mBoundsRectF.bottom - mBoundsRectF.top > bottomEdgeRadius) {
+                mPath.reset();
+                mPath.moveTo(mBoundsRectF.right, mBoundsRectF.top + topEdgeRadius);
+                mPath.cubicTo(mBoundsRectF.right, mBoundsRectF.top + topEdgeRadius,
+                        mBoundsRectF.right, mBoundsRectF.top,
+                        mBoundsRectF.right - topEdgeRadius, mBoundsRectF.top);
+                mPath.lineTo(mBoundsRectF.left + topEdgeRadius, mBoundsRectF.top);
+                mPath.cubicTo(mBoundsRectF.left + topEdgeRadius, mBoundsRectF.top,
+                        mBoundsRectF.left, mBoundsRectF.top,
+                        mBoundsRectF.left, mBoundsRectF.top + topEdgeRadius);
+                mPath.lineTo(mBoundsRectF.left, mBoundsRectF.bottom - bottomEdgeRadius);
+                mPath.cubicTo(mBoundsRectF.left, mBoundsRectF.bottom - bottomEdgeRadius,
+                        mBoundsRectF.left, mBoundsRectF.bottom,
+                        mBoundsRectF.left + bottomEdgeRadius, mBoundsRectF.bottom);
+                mPath.lineTo(mBoundsRectF.right - bottomEdgeRadius, mBoundsRectF.bottom);
+                mPath.cubicTo(mBoundsRectF.right - bottomEdgeRadius, mBoundsRectF.bottom,
+                        mBoundsRectF.right, mBoundsRectF.bottom,
+                        mBoundsRectF.right, mBoundsRectF.bottom - bottomEdgeRadius);
+                mPath.close();
+                canvas.drawPath(mPath, mPaint);
+            }
         } else {
             canvas.drawRect(getBounds().left, getBounds().top, getBounds().right,
                     getBounds().bottom, mPaint);
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
index f68e042..fc89a9e 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
@@ -20,6 +20,7 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.PorterDuff;
@@ -37,6 +38,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.colorextraction.ColorExtractor;
+import com.android.systemui.util.LargeScreenUtils;
 
 import java.util.concurrent.Executor;
 
@@ -102,6 +104,13 @@
     @Override
     protected void onDraw(Canvas canvas) {
         if (mDrawable.getAlpha() > 0) {
+            Resources res = getResources();
+            // Scrim behind notification shade has sharp (not rounded) corners on large screens
+            // which scrim itself cannot know, so we set it here.
+            if (mDrawable instanceof ScrimDrawable) {
+                ((ScrimDrawable) mDrawable).setShouldUseLargeScreenSize(
+                        LargeScreenUtils.shouldUseLargeScreenShadeHeader(res));
+            }
             mDrawable.draw(canvas);
         }
     }
@@ -170,6 +179,15 @@
         });
     }
 
+    /**
+     * Set corner radius of the bottom edge of the Notification scrim.
+     */
+    public void setBottomEdgeRadius(float radius) {
+        if (mDrawable instanceof ScrimDrawable) {
+            ((ScrimDrawable) mDrawable).setBottomEdgeRadius(radius);
+        }
+    }
+
     @VisibleForTesting
     Drawable getDrawable() {
         return mDrawable;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
index 287e810..33a3125 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.content.pm.UserInfo
 import android.os.UserHandle
+import java.util.concurrent.CountDownLatch
 import java.util.concurrent.Executor
 
 /**
@@ -67,14 +68,25 @@
     interface Callback {
 
         /**
+         * Same as {@link onUserChanging(Int, Context, CountDownLatch)} but the latch will be
+         * auto-decremented after the completion of this method.
+         */
+        @JvmDefault
+        fun onUserChanging(newUser: Int, userContext: Context) {}
+
+        /**
          * Notifies that the current user is being changed.
          * Override this method to run things while the screen is frozen for the user switch.
          * Please use {@link #onUserChanged} if the task doesn't need to push the unfreezing of the
          * screen further. Please be aware that code executed in this callback will lengthen the
-         * user switch duration.
+         * user switch duration. When overriding this method, countDown() MUST be called on the
+         * latch once execution is complete.
          */
         @JvmDefault
-        fun onUserChanging(newUser: Int, userContext: Context) {}
+        fun onUserChanging(newUser: Int, userContext: Context, latch: CountDownLatch) {
+            onUserChanging(newUser, userContext)
+            latch.countDown()
+        }
 
         /**
          * Notifies that the current user has changed.
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 3a5d0a7..0b2ae05 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -182,9 +182,22 @@
         Log.i(TAG, "Switching to user $newUserId")
 
         setUserIdInternal(newUserId)
-        notifySubscribers {
-            onUserChanging(newUserId, userContext)
-        }.await()
+
+        val list = synchronized(callbacks) {
+            callbacks.toList()
+        }
+        val latch = CountDownLatch(list.size)
+        list.forEach {
+            val callback = it.callback.get()
+            if (callback != null) {
+                it.executor.execute {
+                    callback.onUserChanging(userId, userContext, latch)
+                }
+            } else {
+                latch.countDown()
+            }
+        }
+        latch.await()
     }
 
     @WorkerThread
@@ -224,25 +237,18 @@
         }
     }
 
-    private inline fun notifySubscribers(
-            crossinline action: UserTracker.Callback.() -> Unit
-    ): CountDownLatch {
+    private inline fun notifySubscribers(crossinline action: UserTracker.Callback.() -> Unit) {
         val list = synchronized(callbacks) {
             callbacks.toList()
         }
-        val latch = CountDownLatch(list.size)
 
         list.forEach {
             if (it.callback.get() != null) {
                 it.executor.execute {
                     it.callback.get()?.action()
-                    latch.countDown()
                 }
-            } else {
-                latch.countDown()
             }
         }
-        return latch
     }
 
     override fun dump(pw: PrintWriter, args: Array<out String>) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index b502b4d..b1987c1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -23,6 +23,7 @@
 import static androidx.constraintlayout.widget.ConstraintSet.END;
 import static androidx.constraintlayout.widget.ConstraintSet.PARENT_ID;
 
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION;
 import static com.android.keyguard.KeyguardClockSwitch.LARGE;
 import static com.android.keyguard.KeyguardClockSwitch.SMALL;
 import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
@@ -71,6 +72,7 @@
 import android.provider.Settings;
 import android.transition.ChangeBounds;
 import android.transition.Transition;
+import android.transition.TransitionListenerAdapter;
 import android.transition.TransitionManager;
 import android.transition.TransitionSet;
 import android.transition.TransitionValues;
@@ -98,6 +100,7 @@
 import androidx.constraintlayout.widget.ConstraintSet;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.SystemBarUtils;
@@ -293,7 +296,19 @@
      * custom clock animation is in use.
      */
     private static final int KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION = 1000;
+    /**
+     * Whether the Shade should animate to reflect Back gesture progress.
+     * To minimize latency at runtime, we cache this, else we'd be reading it every time
+     * updateQsExpansion() is called... and it's called very often.
+     *
+     * Whenever we change this flag, SysUI is restarted, so it's never going to be "stale".
+     */
 
+    public final boolean mAnimateBack;
+    /**
+     * The minimum scale to "squish" the Shade and associated elements down to, for Back gesture
+     */
+    public static final float SHADE_BACK_ANIM_MIN_SCALE = 0.9f;
     private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
     private final Resources mResources;
     private final KeyguardStateController mKeyguardStateController;
@@ -353,6 +368,7 @@
     private final NotificationGutsManager mGutsManager;
     private final AlternateBouncerInteractor mAlternateBouncerInteractor;
     private final QuickSettingsController mQsController;
+    private final InteractionJankMonitor mInteractionJankMonitor;
 
     private long mDownTime;
     private boolean mTouchSlopExceededBeforeDown;
@@ -361,6 +377,8 @@
     private CentralSurfaces mCentralSurfaces;
     private HeadsUpManagerPhone mHeadsUpManager;
     private float mExpandedHeight = 0;
+    /** The current squish amount for the predictive back animation */
+    private float mCurrentBackProgress = 0.0f;
     private boolean mTracking;
     private boolean mHintAnimationRunning;
     private KeyguardBottomAreaView mKeyguardBottomArea;
@@ -465,7 +483,7 @@
     private int mPanelAlpha;
     private Runnable mPanelAlphaEndAction;
     private float mBottomAreaShadeAlpha;
-    private final ValueAnimator mBottomAreaShadeAlphaAnimator;
+    final ValueAnimator mBottomAreaShadeAlphaAnimator;
     private final AnimatableProperty mPanelAlphaAnimator = AnimatableProperty.from("panelAlpha",
             NotificationPanelView::setPanelAlphaInternal,
             NotificationPanelView::getCurrentPanelAlpha,
@@ -597,7 +615,6 @@
     private int mLockscreenToDreamingTransitionTranslationY;
     private int mGoneToDreamingTransitionTranslationY;
     private int mLockscreenToOccludedTransitionTranslationY;
-    private boolean mUnocclusionTransitionFlagEnabled = false;
 
     private final Runnable mFlingCollapseRunnable = () -> fling(0, false /* expand */,
             mNextCollapseSpeedUpFactor, false /* expandBecauseOfFalsing */);
@@ -643,6 +660,19 @@
                     step.getTransitionState() == TransitionState.RUNNING;
             };
 
+    private final TransitionListenerAdapter mKeyguardStatusAlignmentTransitionListener =
+            new TransitionListenerAdapter() {
+                @Override
+                public void onTransitionCancel(Transition transition) {
+                    mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+                }
+
+                @Override
+                public void onTransitionEnd(Transition transition) {
+                    mInteractionJankMonitor.end(CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+                }
+            };
+
     @Inject
     public NotificationPanelViewController(NotificationPanelView view,
             @Main Handler handler,
@@ -707,6 +737,7 @@
             NotificationStackSizeCalculator notificationStackSizeCalculator,
             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
             ShadeTransitionController shadeTransitionController,
+            InteractionJankMonitor interactionJankMonitor,
             SystemClock systemClock,
             KeyguardBottomAreaViewModel keyguardBottomAreaViewModel,
             KeyguardBottomAreaInteractor keyguardBottomAreaInteractor,
@@ -721,6 +752,7 @@
             DumpManager dumpManager,
             KeyguardLongPressViewModel keyguardLongPressViewModel,
             KeyguardInteractor keyguardInteractor) {
+        mInteractionJankMonitor = interactionJankMonitor;
         keyguardStateController.addCallback(new KeyguardStateController.Callback() {
             @Override
             public void onKeyguardFadingAwayChanged() {
@@ -816,6 +848,7 @@
         mShadeHeaderController = shadeHeaderController;
         mLayoutInflater = layoutInflater;
         mFeatureFlags = featureFlags;
+        mAnimateBack = mFeatureFlags.isEnabled(Flags.WM_SHADE_ANIMATE_BACK_GESTURE);
         mFalsingCollector = falsingCollector;
         mPowerManager = powerManager;
         mWakeUpCoordinator = coordinator;
@@ -886,7 +919,6 @@
         mNotificationPanelUnfoldAnimationController = unfoldComponent.map(
                 SysUIUnfoldComponent::getNotificationPanelUnfoldAnimationController);
 
-        mUnocclusionTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
         updateUserSwitcherFlags();
         mKeyguardBottomAreaViewModel = keyguardBottomAreaViewModel;
         mKeyguardBottomAreaInteractor = keyguardBottomAreaInteractor;
@@ -1045,62 +1077,50 @@
         mNotificationPanelUnfoldAnimationController.ifPresent(controller ->
                 controller.setup(mNotificationContainerParent));
 
-        if (mUnocclusionTransitionFlagEnabled) {
-            // Dreaming->Lockscreen
-            collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(),
-                    mDreamingToLockscreenTransition, mMainDispatcher);
-            collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-            collectFlow(mView, mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(
-                    mDreamingToLockscreenTransitionTranslationY),
-                    setTransitionY(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
+        // Dreaming->Lockscreen
+        collectFlow(mView, mKeyguardTransitionInteractor.getDreamingToLockscreenTransition(),
+                mDreamingToLockscreenTransition, mMainDispatcher);
+        collectFlow(mView, mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha(),
+                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+        collectFlow(mView, mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(
+                mDreamingToLockscreenTransitionTranslationY),
+                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
-            // Occluded->Lockscreen
-            collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
-                    mOccludedToLockscreenTransition, mMainDispatcher);
-            collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-            collectFlow(mView, mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(
-                    mOccludedToLockscreenTransitionTranslationY),
-                    setTransitionY(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
+        // Occluded->Lockscreen
+        collectFlow(mView, mKeyguardTransitionInteractor.getOccludedToLockscreenTransition(),
+                mOccludedToLockscreenTransition, mMainDispatcher);
+        collectFlow(mView, mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha(),
+                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+        collectFlow(mView, mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(
+                mOccludedToLockscreenTransitionTranslationY),
+                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
-            // Lockscreen->Dreaming
-            collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(),
-                    mLockscreenToDreamingTransition, mMainDispatcher);
-            collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-            collectFlow(mView, mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(
-                    mLockscreenToDreamingTransitionTranslationY),
-                    setTransitionY(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
+        // Lockscreen->Dreaming
+        collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToDreamingTransition(),
+                mLockscreenToDreamingTransition, mMainDispatcher);
+        collectFlow(mView, mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha(),
+                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+        collectFlow(mView, mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(
+                mLockscreenToDreamingTransitionTranslationY),
+                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
-            // Gone->Dreaming
-            collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
-                    mGoneToDreamingTransition, mMainDispatcher);
-            collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-            collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
-                    mGoneToDreamingTransitionTranslationY),
-                    setTransitionY(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
+        // Gone->Dreaming
+        collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
+                mGoneToDreamingTransition, mMainDispatcher);
+        collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
+                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+        collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
+                mGoneToDreamingTransitionTranslationY),
+                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
 
-            // Lockscreen->Occluded
-            collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
-                    mLockscreenToOccludedTransition, mMainDispatcher);
-            collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
-                    setTransitionAlpha(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-            collectFlow(mView, mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(
-                    mLockscreenToOccludedTransitionTranslationY),
-                    setTransitionY(mNotificationStackScrollLayoutController),
-                    mMainDispatcher);
-        }
+        // Lockscreen->Occluded
+        collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
+                mLockscreenToOccludedTransition, mMainDispatcher);
+        collectFlow(mView, mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha(),
+                setTransitionAlpha(mNotificationStackScrollLayoutController), mMainDispatcher);
+        collectFlow(mView, mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(
+                mLockscreenToOccludedTransitionTranslationY),
+                setTransitionY(mNotificationStackScrollLayoutController), mMainDispatcher);
     }
 
     @VisibleForTesting
@@ -1554,6 +1574,7 @@
             int statusConstraint = shouldBeCentered ? PARENT_ID : R.id.qs_edge_guideline;
             constraintSet.connect(R.id.keyguard_status_view, END, statusConstraint, END);
             if (animate) {
+                mInteractionJankMonitor.begin(mView, CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
                 ChangeBounds transition = new ChangeBounds();
                 if (mSplitShadeEnabled) {
                     // Excluding media from the transition on split-shade, as it doesn't transition
@@ -1577,6 +1598,7 @@
                     // The clock container can sometimes be null. If it is, just fall back to the
                     // old animation rather than setting up the custom animations.
                     if (clockContainerView == null || clockContainerView.getChildCount() == 0) {
+                        transition.addListener(mKeyguardStatusAlignmentTransitionListener);
                         TransitionManager.beginDelayedTransition(
                                 mNotificationContainerParent, transition);
                     } else {
@@ -1595,10 +1617,11 @@
                         adapter.setDuration(KEYGUARD_STATUS_VIEW_CUSTOM_CLOCK_MOVE_DURATION);
                         adapter.addTarget(clockView);
                         set.addTransition(adapter);
-
+                        set.addListener(mKeyguardStatusAlignmentTransitionListener);
                         TransitionManager.beginDelayedTransition(mNotificationContainerParent, set);
                     }
                 } else {
+                    transition.addListener(mKeyguardStatusAlignmentTransitionListener);
                     TransitionManager.beginDelayedTransition(
                             mNotificationContainerParent, transition);
                 }
@@ -1965,6 +1988,14 @@
             if (mFixedDuration != NO_FIXED_DURATION) {
                 animator.setDuration(mFixedDuration);
             }
+
+            // Reset Predictive Back animation's transform after Shade is completely hidden.
+            animator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    resetBackTransformation();
+                }
+            });
         }
         animator.addListener(new AnimatorListenerAdapter() {
             private boolean mCancelled;
@@ -2189,6 +2220,53 @@
         }
     }
 
+    /**
+     * When the back gesture triggers a fully-expanded shade --> QQS shade collapse transition,
+     * the expansionFraction goes down from 1.0 --> 0.0 (collapsing), so the current "squish" amount
+     * (mCurrentBackProgress) must be un-applied from various UI elements in tandem, such that,
+     * as the shade ends up in its half-expanded state (with QQS above), it is back at 100% scale.
+     * Without this, the shade would collapse, and stay squished.
+     */
+    public void adjustBackAnimationScale(float expansionFraction) {
+        if (expansionFraction > 0.0f) { // collapsing
+            float animatedFraction = expansionFraction * mCurrentBackProgress;
+            applyBackScaling(animatedFraction);
+        } else {
+            // collapsed! reset, so that if we re-expand shade, it won't start off "squished"
+            mCurrentBackProgress = 0;
+        }
+    }
+
+    //TODO(b/270981268): allow cancelling back animation mid-flight
+    /** Called when Back gesture has been committed (i.e. a back event has definitely occurred) */
+    public void onBackPressed() {
+        closeQsIfPossible();
+    }
+    /** Sets back progress. */
+    public void onBackProgressed(float progressFraction) {
+        // TODO: non-linearly transform progress fraction into squish amount (ease-in, linear out)
+        mCurrentBackProgress = progressFraction;
+        applyBackScaling(progressFraction);
+    }
+
+    /** Resets back progress. */
+    public void resetBackTransformation() {
+        mCurrentBackProgress = 0.0f;
+        applyBackScaling(0.0f);
+    }
+
+    /** Scales multiple elements in tandem to achieve the illusion of the QS+Shade shrinking
+     *  as a single visual element (used by the Predictive Back Gesture preview animation).
+     *  fraction = 0 implies "no scaling", and 1 means "scale down to minimum size (90%)".
+     */
+    public void applyBackScaling(float fraction) {
+        if (mNotificationContainerParent == null) {
+            return;
+        }
+        float scale = MathUtils.lerp(1.0f, SHADE_BACK_ANIM_MIN_SCALE, fraction);
+        mNotificationContainerParent.applyBackScaling(scale, mSplitShadeEnabled);
+        mScrimController.applyBackScaling(scale);
+    }
     /** */
     public float getLockscreenShadeDragProgress() {
         // mTransitioningToFullShadeProgress > 0 means we're doing regular lockscreen to shade
@@ -2480,9 +2558,6 @@
     }
 
     private void onExpandingFinished() {
-        if (!mUnocclusionTransitionFlagEnabled) {
-            mScrimController.onExpandingFinished();
-        }
         mNotificationStackScrollLayoutController.onExpansionStopped();
         mHeadsUpManager.onExpandingFinished();
         mConversationNotificationManager.onNotificationPanelExpandStateChanged(isFullyCollapsed());
@@ -4868,6 +4943,11 @@
 
             switch (event.getActionMasked()) {
                 case MotionEvent.ACTION_DOWN:
+                    if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE && mAnimateBack) {
+                        // Cache the gesture insets now, so we can quickly query them during
+                        // ACTION_MOVE and decide whether to intercept events for back gesture anim.
+                        mQsController.updateGestureInsetsCache();
+                    }
                     mShadeLog.logMotionEvent(event, "onTouch: down action");
                     startExpandMotion(x, y, false /* startTracking */, mExpandedHeight);
                     mMinExpandHeight = 0.0f;
@@ -4917,6 +4997,12 @@
                     }
                     break;
                 case MotionEvent.ACTION_MOVE:
+                    // If the shade is half-collapsed, a horizontal swipe inwards from L/R edge
+                    // must be routed to the back gesture (which shows a preview animation).
+                    if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE && mAnimateBack
+                            && mQsController.shouldBackBypassQuickSettings(x)) {
+                        return false;
+                    }
                     if (isFullyCollapsed()) {
                         // If panel is fully collapsed, reset haptic effect before adding movement.
                         mHasVibratedOnOpen = false;
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 60fa865..c130b39 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -38,8 +38,6 @@
 import com.android.systemui.R;
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.dock.DockManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -47,6 +45,7 @@
 import com.android.systemui.keyguard.shared.model.TransitionStep;
 import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationInsetsController;
@@ -132,11 +131,11 @@
             NotificationInsetsController notificationInsetsController,
             AmbientState ambientState,
             PulsingGestureListener pulsingGestureListener,
-            FeatureFlags featureFlags,
             KeyguardBouncerViewModel keyguardBouncerViewModel,
             KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
             AlternateBouncerInteractor alternateBouncerInteractor,
-            KeyguardTransitionInteractor keyguardTransitionInteractor
+            KeyguardTransitionInteractor keyguardTransitionInteractor,
+            PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel
     ) {
         mLockscreenShadeTransitionController = transitionController;
         mFalsingCollector = falsingCollector;
@@ -163,12 +162,11 @@
         KeyguardBouncerViewBinder.bind(
                 mView.findViewById(R.id.keyguard_bouncer_container),
                 keyguardBouncerViewModel,
+                primaryBouncerToGoneTransitionViewModel,
                 keyguardBouncerComponentFactory);
 
-        if (featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION)) {
-            collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
-                    mLockscreenToDreamingTransition);
-        }
+        collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
+                mLockscreenToDreamingTransition);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
index f73dde6..7dff6ea 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQuickSettingsContainer.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.WindowInsets;
@@ -55,6 +56,13 @@
     private QS mQs;
     private View mQSContainer;
 
+    /**
+     *  These are used to compute the bounding box containing the shade and the notification scrim,
+     *  which is then used to drive the Back gesture animation.
+     */
+    private final Rect mUpperRect = new Rect();
+    private final Rect mBoundingBoxRect = new Rect();
+
     @Nullable
     private Consumer<Configuration> mConfigurationChangedListener;
 
@@ -172,4 +180,37 @@
     public void applyConstraints(ConstraintSet constraintSet) {
         constraintSet.applyTo(this);
     }
+
+    /**
+     *  Scale multiple elements in tandem, for the predictive back animation.
+     *  This is how the Shade responds to the Back gesture (by scaling).
+     *  Without the common center, individual elements will scale about their respective centers.
+     *  Scaling the entire NotificationsQuickSettingsContainer will also resize the shade header
+     *  (which we don't want).
+     */
+    public void applyBackScaling(float scale, boolean usingSplitShade) {
+        if (mStackScroller == null || mQSContainer == null) {
+            return;
+        }
+
+        mQSContainer.getBoundsOnScreen(mUpperRect);
+        mStackScroller.getBoundsOnScreen(mBoundingBoxRect);
+        mBoundingBoxRect.union(mUpperRect);
+
+        float cx = mBoundingBoxRect.centerX();
+        float cy = mBoundingBoxRect.centerY();
+
+        mQSContainer.setPivotX(cx);
+        mQSContainer.setPivotY(cy);
+        mQSContainer.setScaleX(scale);
+        mQSContainer.setScaleY(scale);
+
+        // When in large-screen split-shade mode, the notification stack scroller scales correctly
+        // only if the pivot point is at the left edge of the screen (because of its dimensions).
+        // When not in large-screen split-shade mode, we can scale correctly via the (cx,cy) above.
+        mStackScroller.setPivotX(usingSplitShade ? 0.0f : cx);
+        mStackScroller.setPivotY(cy);
+        mStackScroller.setScaleX(scale);
+        mStackScroller.setScaleY(scale);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index 099ad94..6857f4c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -31,6 +31,7 @@
 import android.animation.ValueAnimator;
 import android.app.Fragment;
 import android.content.res.Resources;
+import android.graphics.Insets;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.util.Log;
@@ -40,6 +41,9 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.FrameLayout;
 
@@ -63,6 +67,7 @@
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.screenrecord.RecordingController;
 import com.android.systemui.shade.transition.ShadeTransitionController;
+import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
@@ -83,10 +88,10 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.LargeScreenUtils;
 
-import javax.inject.Inject;
-
 import dagger.Lazy;
 
+import javax.inject.Inject;
+
 /** Handles QuickSettings touch handling, expansion and animation state
  * TODO (b/264460656) make this dumpable
  */
@@ -223,6 +228,13 @@
     private boolean mAnimatorExpand;
 
     /**
+     * The gesture inset currently in effect -- used to decide whether a back gesture should
+     * receive a horizontal swipe inwards from the left/right vertical edge of the screen.
+     * We cache this on ACTION_DOWN, and query it during both ACTION_DOWN and ACTION_MOVE events.
+     */
+    private Insets mCachedGestureInsets;
+
+    /**
      * The amount of progress we are currently in if we're transitioning to the full shade.
      * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
      * shade. This value can also go beyond 1.1 when we're overshooting!
@@ -406,6 +418,7 @@
         mQuickQsHeaderHeight = mLargeScreenShadeHeaderHeight;
 
         mEnableClipping = mResources.getBoolean(R.bool.qs_enable_clipping);
+        updateGestureInsetsCache();
     }
 
     // TODO (b/265054088): move this and others to a CoreStartable
@@ -469,6 +482,26 @@
                 || touchX > mQsFrame.getX() + mQsFrame.getWidth();
     }
 
+    /**
+     *  Computes (and caches) the gesture insets for the current window. Intended to be called
+     *  on ACTION_DOWN, and safely queried repeatedly thereafter during ACTION_MOVE events.
+     */
+    public void updateGestureInsetsCache() {
+        WindowManager wm = this.mPanelView.getContext().getSystemService(WindowManager.class);
+        WindowMetrics windowMetrics = wm.getCurrentWindowMetrics();
+        mCachedGestureInsets = windowMetrics.getWindowInsets().getInsets(
+                WindowInsets.Type.systemGestures());
+    }
+
+    /**
+     *  Returns whether x coordinate lies in the vertical edges of the screen
+     *  (the only place where a back gesture can be initiated).
+     */
+    public boolean shouldBackBypassQuickSettings(float touchX) {
+        return (touchX < mCachedGestureInsets.left)
+                || (touchX > mKeyguardStatusBar.getWidth() - mCachedGestureInsets.right);
+    }
+
     /** Returns whether touch is within QS area */
     private boolean isTouchInQsArea(float x, float y) {
         if (isSplitShadeAndTouchXOutsideQs(x)) {
@@ -926,6 +959,10 @@
                 getHeaderTranslation(),
                 squishiness
         );
+        if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE
+                && mPanelViewControllerLazy.get().mAnimateBack) {
+            mPanelViewControllerLazy.get().adjustBackAnimationScale(adjustedExpansionFraction);
+        }
         mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
         int qsPanelBottomY = calculateBottomPosition(qsExpansionFraction);
         mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
@@ -1113,6 +1150,7 @@
             float screenCornerRadius = mRecordingController.isRecording() ? 0 : mScreenCornerRadius;
             radius = (int) MathUtils.lerp(screenCornerRadius, mScrimCornerRadius,
                     Math.min(top / (float) mScrimCornerRadius, 1f));
+            mScrimController.setNotificationBottomRadius(radius);
         }
         if (isQsFragmentCreated()) {
             float qsTranslation = 0;
@@ -1505,18 +1543,31 @@
     }
 
     private void handleDown(MotionEvent event) {
-        if (event.getActionMasked() == MotionEvent.ACTION_DOWN
-                && shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
-            mFalsingCollector.onQsDown();
-            mShadeLog.logMotionEvent(event, "handleQsDown: down action, QS tracking enabled");
-            mTracking = true;
-            onExpansionStarted();
-            mInitialHeightOnTouch = mExpansionHeight;
-            mInitialTouchY = event.getY();
-            mInitialTouchX = event.getX();
-            // TODO (b/265193930): remove dependency on NPVC
-            // If we interrupt an expansion gesture here, make sure to update the state correctly.
-            mPanelViewControllerLazy.get().notifyExpandingFinished();
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            // When the shade is fully-expanded, an inward swipe from the L/R edge should first
+            // allow the back gesture's animation to preview the shade animation (if enabled).
+            // (swipes starting closer to the center of the screen will not be affected)
+            if (QuickStepContract.ALLOW_BACK_GESTURE_IN_SHADE
+                    && mPanelViewControllerLazy.get().mAnimateBack) {
+                updateGestureInsetsCache();
+                if (shouldBackBypassQuickSettings(event.getX())) {
+                    return;
+                }
+            }
+            if (shouldQuickSettingsIntercept(event.getX(), event.getY(), -1)) {
+                mFalsingCollector.onQsDown();
+                mShadeLog.logMotionEvent(event,
+                        "handleQsDown: down action, QS tracking enabled");
+                mTracking = true;
+                onExpansionStarted();
+                mInitialHeightOnTouch = mExpansionHeight;
+                mInitialTouchY = event.getY();
+                mInitialTouchX = event.getX();
+                // TODO (b/265193930): remove dependency on NPVC
+                // If we interrupt an expansion gesture here, make sure to update the state
+                // correctly.
+                mPanelViewControllerLazy.get().notifyExpandingFinished();
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
index a1767cc..f4b1cc5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt
@@ -107,7 +107,7 @@
      *
      * @param fraction the fraction from the expansion in [0, 1]
      * @param expanded whether the panel is currently expanded; this is independent from the
-     * fraction as the panel also might be expanded if the fraction is 0.
+     *   fraction as the panel also might be expanded if the fraction is 0.
      * @param tracking whether we're currently tracking the user's gesture.
      */
     fun onPanelExpansionChanged(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index 37773e9..b79f32a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -70,9 +70,9 @@
  *
  * [header] is a [MotionLayout] that has two transitions:
  * * [HEADER_TRANSITION_ID]: [QQS_HEADER_CONSTRAINT] <-> [QS_HEADER_CONSTRAINT] for portrait
- * handheld device configuration.
+ *   handheld device configuration.
  * * [LARGE_SCREEN_HEADER_TRANSITION_ID]: [LARGE_SCREEN_HEADER_CONSTRAINT] for all other
- * configurations
+ *   configurations
  */
 @CentralSurfacesScope
 class ShadeHeaderController
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
index e9fac28..1cfb400 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutsReceiver.java
@@ -39,7 +39,7 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
-        if (mIsShortcutListSearchEnabled && Utilities.isTablet(context)) {
+        if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(context)) {
             if (Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS.equals(intent.getAction())) {
                 KeyboardShortcutListSearch.show(context, -1 /* deviceId unknown */);
             } else if (Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS.equals(intent.getAction())) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
index 62c225b..df8c6ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt
@@ -148,7 +148,8 @@
               qsDragFraction: $qsTransitionFraction
               qsSquishFraction: $qsSquishTransitionFraction
               isTransitioningToFullShade: $isTransitioningToFullShade
-        """.trimIndent()
+        """
+                .trimIndent()
         )
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index f0d064b..9a9503c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -572,8 +572,7 @@
             entry.setGroupExpansionChanging(true)
             userId = entry.sbn.userId
         }
-        var fullShadeNeedsBouncer = (!lockScreenUserManager.userAllowsPrivateNotificationsInPublic(
-                lockScreenUserManager.getCurrentUserId()) ||
+        var fullShadeNeedsBouncer = (
                 !lockScreenUserManager.shouldShowLockscreenNotifications() ||
                 falsingCollector.shouldEnforceBouncer())
         if (keyguardBypassController.bypassEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
index 42b874f..7297ae6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ui/MobileContextProvider.kt
@@ -74,7 +74,7 @@
 
     /**
      * @return a context with the MCC/MNC [Configuration] values corresponding to this
-     * subscriptionId
+     *   subscriptionId
      */
     fun getMobileContextForSub(subId: Int, context: Context): Context {
         if (demoModeController.isInDemoMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
index 64b7ac9..5fa83ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLegacyImpl.kt
@@ -39,6 +39,7 @@
  *      - Simple prioritization: Privacy > Battery > connectivity (encoded in [StatusEvent])
  *      - Only schedules a single event, and throws away lowest priority events
  * ```
+ *
  * There are 4 basic stages of animation at play here:
  * ```
  *      1. System chrome animation OUT
@@ -46,6 +47,7 @@
  *      3. Chip animation OUT; potentially into a dot
  *      4. System chrome animation IN
  * ```
+ *
  * Thus we can keep all animations synchronized with two separate ValueAnimators, one for system
  * chrome and the other for the chip. These can animate from 0,1 and listeners can parameterize
  * their respective views based on the progress of the animator. Interpolation differences TBD
@@ -168,7 +170,7 @@
      * 3. Update the scheduler state so that clients know where we are
      * 4. Maybe: provide scaffolding such as: dot location, margins, etc
      * 5. Maybe: define a maximum animation length and enforce it. Probably only doable if we
-     * collect all of the animators and run them together.
+     *    collect all of the animators and run them together.
      */
     private fun runChipAnimation() {
         statusBarWindowController.setForceStatusBarVisible(true)
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 f395bea..82c5ee6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -334,9 +334,9 @@
         }
 
         val ssView = plugin.getView(parent)
+        configPlugin?.let { ssView.registerConfigProvider(it) }
         ssView.setUiSurface(BcSmartspaceDataPlugin.UI_SURFACE_LOCK_SCREEN_AOD)
         ssView.registerDataProvider(plugin)
-        configPlugin?.let { ssView.registerConfigProvider(it) }
 
         ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
             override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 0a5e986..11582d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -29,7 +29,6 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.SynchronousUserSwitchObserver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -52,7 +51,9 @@
 import com.android.systemui.CoreStartable;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.NotificationChannels;
@@ -73,6 +74,8 @@
 
     private final Context mContext;
     private final Handler mHandler = new Handler();
+    private final UserTracker mUserTracker;
+    private final Executor mMainExecutor;
     private final Executor mUiBgExecutor;
     private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
     private final CommandQueue mCommandQueue;
@@ -82,10 +85,14 @@
     public InstantAppNotifier(
             Context context,
             CommandQueue commandQueue,
+            UserTracker userTracker,
+            @Main Executor mainExecutor,
             @UiBackground Executor uiBgExecutor,
             KeyguardStateController keyguardStateController) {
         mContext = context;
         mCommandQueue = commandQueue;
+        mUserTracker = userTracker;
+        mMainExecutor = mainExecutor;
         mUiBgExecutor = uiBgExecutor;
         mKeyguardStateController = keyguardStateController;
     }
@@ -93,11 +100,7 @@
     @Override
     public void start() {
         // listen for user / profile change.
-        try {
-            ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
-        } catch (RemoteException e) {
-            // Ignore
-        }
+        mUserTracker.addCallback(mUserSwitchListener, mMainExecutor);
 
         mCommandQueue.addCallback(this);
         mKeyguardStateController.addCallback(this);
@@ -129,13 +132,10 @@
         updateForegroundInstantApps();
     }
 
-    private final SynchronousUserSwitchObserver mUserSwitchListener =
-            new SynchronousUserSwitchObserver() {
+    private final UserTracker.Callback mUserSwitchListener =
+            new UserTracker.Callback() {
                 @Override
-                public void onUserSwitching(int newUserId) throws RemoteException {}
-
-                @Override
-                public void onUserSwitchComplete(int newUserId) throws RemoteException {
+                public void onUserChanged(int newUser, Context userContext) {
                     mHandler.post(
                             () -> {
                                 updateForegroundInstantApps();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
index fc89be2..00d8c42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
@@ -28,10 +28,6 @@
     val featureFlags: FeatureFlags,
     val sysPropFlags: FlagResolver,
 ) {
-    init {
-        featureFlags.addListener(Flags.DISABLE_FSI) { event -> event.requestNoRestart() }
-    }
-
     fun isDevLoggingEnabled(): Boolean =
         featureFlags.isEnabled(Flags.NOTIFICATION_PIPELINE_DEVELOPER_LOGGING)
 
@@ -40,8 +36,6 @@
 
     fun fsiOnDNDUpdate(): Boolean = featureFlags.isEnabled(Flags.FSI_ON_DND_UPDATE)
 
-    fun disableFsi(): Boolean = featureFlags.isEnabled(Flags.DISABLE_FSI)
-
     fun forceDemoteFsi(): Boolean =
             sysPropFlags.isEnabled(NotificationFlags.FSI_FORCE_DEMOTE)
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index 7e53d54..8874f59 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -18,6 +18,7 @@
 
 import android.animation.ObjectAnimator
 import android.util.FloatProperty
+import androidx.annotation.VisibleForTesting
 import com.android.systemui.Dumpable
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.dagger.SysUISingleton
@@ -302,29 +303,29 @@
             // the doze amount to 0f (not dozing) so that the notifications are no longer hidden.
             // See: UnlockedScreenOffAnimationController.onFinishedWakingUp()
             setDozeAmount(0f, 0f, source = "Override: Shade->Shade (lock cancelled by unlock)")
+            this.state = newState
+            return
         }
 
         if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) {
+            this.state = newState
             return
         }
 
         if (overrideDozeAmountIfBypass()) {
+            this.state = newState
             return
         }
 
         maybeClearDozeAmountOverrideHidingNotifs()
 
-        if (bypassController.bypassEnabled &&
-                newState == StatusBarState.KEYGUARD && state == StatusBarState.SHADE_LOCKED &&
-            (!statusBarStateController.isDozing || shouldAnimateVisibility())) {
-            // We're leaving shade locked. Let's animate the notifications away
-            setNotificationsVisible(visible = true, increaseSpeed = false, animate = false)
-            setNotificationsVisible(visible = false, increaseSpeed = false, animate = true)
-        }
-
         this.state = newState
     }
 
+    @VisibleForTesting
+    val statusBarState: Int
+        get() = state
+
     override fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
         val collapsedEnough = event.fraction <= 0.9f
         if (collapsedEnough != this.collapsedEnoughToHide) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
index 4464531..88d9ffc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
@@ -13,7 +13,7 @@
 
 package com.android.systemui.statusbar.notification
 
-import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.log.dagger.NotificationLockscreenLog
 import com.android.systemui.plugins.log.LogBuffer
 import com.android.systemui.plugins.log.LogLevel.DEBUG
 import com.android.systemui.statusbar.StatusBarState
@@ -21,7 +21,12 @@
 
 class NotificationWakeUpCoordinatorLogger
 @Inject
-constructor(@NotificationLog private val buffer: LogBuffer) {
+constructor(@NotificationLockscreenLog private val buffer: LogBuffer) {
+    private var lastSetDozeAmountLogWasFractional = false
+    private var lastSetDozeAmountLogState = -1
+    private var lastSetDozeAmountLogSource = "undefined"
+    private var lastOnDozeAmountChangedLogWasFractional = false
+
     fun logSetDozeAmount(
         linear: Float,
         eased: Float,
@@ -29,6 +34,20 @@
         state: Int,
         changed: Boolean,
     ) {
+        // Avoid logging on every frame of the animation if important values are not changing
+        val isFractional = linear != 1f && linear != 0f
+        if (
+            lastSetDozeAmountLogWasFractional &&
+                isFractional &&
+                lastSetDozeAmountLogState == state &&
+                lastSetDozeAmountLogSource == source
+        ) {
+            return
+        }
+        lastSetDozeAmountLogWasFractional = isFractional
+        lastSetDozeAmountLogState = state
+        lastSetDozeAmountLogSource = source
+
         buffer.log(
             TAG,
             DEBUG,
@@ -66,6 +85,10 @@
     }
 
     fun logOnDozeAmountChanged(linear: Float, eased: Float) {
+        // Avoid logging on every frame of the animation when values are fractional
+        val isFractional = linear != 1f && linear != 0f
+        if (lastOnDozeAmountChangedLogWasFractional && isFractional) return
+        lastOnDozeAmountChangedLogWasFractional = isFractional
         buffer.log(
             TAG,
             DEBUG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
index a35617c..6deef2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt
@@ -315,6 +315,7 @@
 
 /**
  * State object for a `Roundable` class.
+ *
  * @param targetView Will handle the [AnimatableProperty]
  * @param roundable Target of the radius animation
  * @param maxRadius Max corner radius in pixels
@@ -436,7 +437,6 @@
          * This is the most convenient way to define a new [SourceType].
          *
          * For example:
-         *
          * ```kotlin
          *     private val SECTION = SourceType.from("Section")
          * ```
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
index 1fccf82..0a9dddc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DismissibilityCoordinator.kt
@@ -46,6 +46,7 @@
 
     /**
      * Visits every entry and its children to mark the dismissible entries.
+     *
      * @param markedKeys set to store the marked entry keys
      * @param entries to visit
      * @param isLocked the locked state of the device
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt
deleted file mode 100644
index b483228..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepo.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.app.PendingIntent
-import android.content.Context
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import android.os.RemoteException
-import android.service.dreams.IDreamManager
-import com.android.systemui.CoreStartable
-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.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import java.util.concurrent.Executor
-import javax.inject.Inject
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
-
-/**
- * Class that bridges the gap between clean app architecture and existing code. Provides new
- * implementation of StatusBarNotificationActivityStarter launchFullscreenIntent that pipes
- * one-directional data => FsiChromeViewModel => FsiChromeView.
- */
-@SysUISingleton
-class FsiChromeRepo
-@Inject
-constructor(
-    private val context: Context,
-    private val pm: PackageManager,
-    private val keyguardRepo: KeyguardRepository,
-    private val launchFullScreenIntentProvider: LaunchFullScreenIntentProvider,
-    private val featureFlags: FeatureFlags,
-    private val uiBgExecutor: Executor,
-    private val dreamManager: IDreamManager,
-    private val centralSurfaces: CentralSurfaces
-) : CoreStartable {
-
-    companion object {
-        private const val classTag = "FsiChromeRepo"
-    }
-
-    data class FSIInfo(
-        val appName: String,
-        val appIcon: Drawable,
-        val fullscreenIntent: PendingIntent
-    )
-
-    private val _infoFlow = MutableStateFlow<FSIInfo?>(null)
-    val infoFlow: StateFlow<FSIInfo?> = _infoFlow
-
-    override fun start() {
-        log("$classTag start listening for FSI notifications")
-
-        // Listen for FSI launch events for the lifetime of SystemUI.
-        launchFullScreenIntentProvider.registerListener { entry -> launchFullscreenIntent(entry) }
-    }
-
-    fun dismiss() {
-        _infoFlow.value = null
-    }
-
-    fun onFullscreen() {
-        // TODO(b/243421660) implement transition from container to fullscreen
-    }
-
-    fun stopScreenSaver() {
-        uiBgExecutor.execute {
-            try {
-                dreamManager.awaken()
-            } catch (e: RemoteException) {
-                e.printStackTrace()
-            }
-        }
-    }
-
-    fun launchFullscreenIntent(entry: NotificationEntry) {
-        if (!featureFlags.isEnabled(Flags.FSI_CHROME)) {
-            return
-        }
-        if (!keyguardRepo.isKeyguardShowing()) {
-            return
-        }
-        stopScreenSaver()
-
-        var appName = pm.getApplicationLabel(context.applicationInfo) as String
-        val appIcon = pm.getApplicationIcon(context.packageName)
-        val fullscreenIntent = entry.sbn.notification.fullScreenIntent
-
-        log("FsiChromeRepo launchFullscreenIntent appName=$appName appIcon $appIcon")
-        _infoFlow.value = FSIInfo(appName, appIcon, fullscreenIntent)
-
-        // If screen is off or we're showing AOD, show lockscreen.
-        centralSurfaces.wakeUpForFullScreenIntent()
-
-        // Don't show HUN since we're already showing FSI.
-        entry.notifyFullScreenIntentLaunched()
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt
deleted file mode 100644
index 6e5fcf4..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeView.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.content.Context
-import android.graphics.Color
-import android.graphics.Color.DKGRAY
-import android.graphics.Outline
-import android.util.AttributeSet
-import android.view.View
-import android.view.ViewOutlineProvider
-import android.widget.Button
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.TextView
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-
-@SysUISingleton
-class FsiChromeView
-@JvmOverloads
-constructor(
-    context: Context?,
-    attrs: AttributeSet? = null,
-    defStyleAttr: Int = 0,
-    defStyleRes: Int = 0
-) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {
-
-    companion object {
-        private const val classTag = "FsiChromeView"
-    }
-
-    lateinit var chromeContainer: LinearLayout
-    lateinit var appIconImageView: ImageView
-    lateinit var appNameTextView: TextView
-    lateinit var dismissButton: Button
-    lateinit var fullscreenButton: Button
-
-    private val cornerRadius: Float =
-        resources.getDimensionPixelSize(R.dimen.notification_corner_radius).toFloat()
-    private val vertPadding: Int =
-        resources.getDimensionPixelSize(R.dimen.fsi_chrome_vertical_padding)
-    private val sidePadding: Int =
-        resources.getDimensionPixelSize(R.dimen.notification_side_paddings)
-
-    init {
-        log("$classTag init")
-    }
-
-    override fun onFinishInflate() {
-        log("$classTag onFinishInflate")
-        super.onFinishInflate()
-
-        setBackgroundColor(Color.TRANSPARENT)
-        setPadding(
-            sidePadding,
-            vertPadding,
-            sidePadding,
-            vertPadding
-        ) // Make smaller than fullscreen.
-
-        chromeContainer = findViewById(R.id.fsi_chrome)
-        chromeContainer.setBackgroundColor(DKGRAY)
-
-        appIconImageView = findViewById(R.id.fsi_app_icon)
-        appNameTextView = findViewById(R.id.fsi_app_name)
-        dismissButton = findViewById(R.id.fsi_dismiss_button)
-        fullscreenButton = findViewById(R.id.fsi_fullscreen_button)
-
-        outlineProvider =
-            object : ViewOutlineProvider() {
-                override fun getOutline(view: View, outline: Outline) {
-                    outline.setRoundRect(
-                        /* left */ sidePadding,
-                        /* top */ vertPadding,
-                        /* right */ view.width - sidePadding,
-                        /* bottom */ view.height - vertPadding,
-                        cornerRadius
-                    )
-                }
-            }
-        clipToOutline = true
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
deleted file mode 100644
index 1a3927b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewBinder.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.WindowManager
-import com.android.systemui.CoreStartable
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-import java.util.concurrent.Executor
-import javax.inject.Inject
-
-@SysUISingleton
-class FsiChromeViewBinder
-@Inject
-constructor(
-    val context: Context,
-    val windowManager: WindowManager,
-    val viewModelFactory: FsiChromeViewModelFactory,
-    val layoutInflater: LayoutInflater,
-    val centralSurfaces: CentralSurfaces,
-    @Main val mainExecutor: Executor,
-    @Application val scope: CoroutineScope,
-) : CoreStartable {
-
-    companion object {
-        private const val classTag = "FsiChromeViewBinder"
-    }
-
-    private val fsiChromeView =
-        layoutInflater.inflate(R.layout.fsi_chrome_view, null /* root */, false /* attachToRoot */)
-            as FsiChromeView
-
-    var addedToWindowManager = false
-    var cornerRadius: Int = context.resources.getDimensionPixelSize(
-            R.dimen.notification_corner_radius)
-
-    override fun start() {
-        val methodTag = "start"
-        log("$classTag $methodTag ")
-
-        scope.launch {
-            log("$classTag $methodTag launch ")
-            viewModelFactory.viewModelFlow.collect { vm -> updateForViewModel(vm) }
-        }
-    }
-
-    private fun updateForViewModel(vm: FsiChromeViewModel?) {
-        val methodTag = "updateForViewModel"
-
-        if (vm == null) {
-            log("$classTag $methodTag viewModel is null, removing from window manager")
-
-            if (addedToWindowManager) {
-                windowManager.removeView(fsiChromeView)
-                addedToWindowManager = false
-            }
-            return
-        }
-
-        bindViewModel(vm, windowManager)
-
-        if (addedToWindowManager) {
-            log("$classTag $methodTag already addedToWindowManager")
-        } else {
-            windowManager.addView(fsiChromeView, FsiTaskViewConfig.getWmLayoutParams("PackageName"))
-            addedToWindowManager = true
-        }
-    }
-
-    private fun bindViewModel(
-        vm: FsiChromeViewModel,
-        windowManager: WindowManager,
-    ) {
-        log("$classTag bindViewModel")
-
-        fsiChromeView.appIconImageView.setImageDrawable(vm.appIcon)
-        fsiChromeView.appNameTextView.text = vm.appName
-
-        fsiChromeView.dismissButton.setOnClickListener { vm.onDismiss() }
-        fsiChromeView.fullscreenButton.setOnClickListener { vm.onFullscreen() }
-
-        vm.taskView.cornerRadius = cornerRadius.toFloat()
-        vm.taskView.startActivity(
-            vm.fsi,
-            FsiTaskViewConfig.getFillInIntent(),
-            FsiTaskViewConfig.getActivityOptions(context, windowManager),
-            FsiTaskViewConfig.getLaunchBounds(windowManager)
-        )
-
-        log("$classTag bindViewModel started taskview activity")
-        fsiChromeView.addView(vm.taskView)
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt
deleted file mode 100644
index 1ca698b..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactory.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.annotation.UiContext
-import android.app.PendingIntent
-import android.content.Context
-import android.graphics.drawable.Drawable
-import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.statusbar.notification.fsi.FsiDebug.Companion.log
-import com.android.wm.shell.TaskView
-import com.android.wm.shell.TaskViewFactory
-import java.util.Optional
-import java.util.concurrent.Executor
-import javax.inject.Inject
-import kotlin.coroutines.resume
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.mapLatest
-import kotlinx.coroutines.suspendCancellableCoroutine
-
-/**
- * Handle view-related data for fullscreen intent container on lockscreen. Wraps FsiChromeRepo,
- * transforms events/state into view-relevant representation for FsiChromeView. Alive for lifetime
- * of SystemUI.
- */
-@SysUISingleton
-class FsiChromeViewModelFactory
-@Inject
-constructor(
-    val repo: FsiChromeRepo,
-    val taskViewFactory: Optional<TaskViewFactory>,
-    @UiContext val context: Context,
-    @Main val mainExecutor: Executor,
-) : CoreStartable {
-
-    companion object {
-        private const val classTag = "FsiChromeViewModelFactory"
-    }
-
-    val viewModelFlow: Flow<FsiChromeViewModel?> =
-        repo.infoFlow.mapLatest { fsiInfo ->
-            fsiInfo?.let {
-                log("$classTag viewModelFlow got new fsiInfo")
-
-                // mapLatest emits null when FSIInfo is null
-                FsiChromeViewModel(
-                    fsiInfo.appName,
-                    fsiInfo.appIcon,
-                    createTaskView(),
-                    fsiInfo.fullscreenIntent,
-                    repo
-                )
-            }
-        }
-
-    override fun start() {
-        log("$classTag start")
-    }
-
-    private suspend fun createTaskView(): TaskView = suspendCancellableCoroutine { k ->
-        log("$classTag createTaskView")
-
-        taskViewFactory.get().create(context, mainExecutor) { taskView -> k.resume(taskView) }
-    }
-}
-
-// Alive for lifetime of FSI.
-data class FsiChromeViewModel(
-    val appName: String,
-    val appIcon: Drawable,
-    val taskView: TaskView,
-    val fsi: PendingIntent,
-    val repo: FsiChromeRepo
-) {
-    companion object {
-        private const val classTag = "FsiChromeViewModel"
-    }
-
-    fun onDismiss() {
-        log("$classTag onDismiss")
-        repo.dismiss()
-    }
-    fun onFullscreen() {
-        log("$classTag onFullscreen")
-        repo.onFullscreen()
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt
deleted file mode 100644
index d9e3f8f..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiDebug.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-class FsiDebug {
-
-    companion object {
-        private const val debugTag = "FsiDebug"
-        private const val debug = true
-
-        fun log(s: Any) {
-            if (!debug) {
-                return
-            }
-            android.util.Log.d(debugTag, "$s")
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
deleted file mode 100644
index 034ab56..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/fsi/FsiTaskViewConfig.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.android.systemui.statusbar.notification.fsi
-
-import android.app.ActivityOptions
-import android.content.Context
-import android.content.Intent
-import android.graphics.PixelFormat
-import android.graphics.Rect
-import android.os.Binder
-import android.view.ViewGroup
-import android.view.WindowManager
-
-/**
- * Config for adding the FsiChromeView window to WindowManager and starting the FSI activity.
- */
-class FsiTaskViewConfig {
-
-    companion object {
-
-        private const val classTag = "FsiTaskViewConfig"
-
-        fun getWmLayoutParams(packageName: String): WindowManager.LayoutParams {
-            val params: WindowManager.LayoutParams?
-            params =
-                WindowManager.LayoutParams(
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
-                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE or
-                        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED or
-                            WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER,
-                    PixelFormat.TRANSLUCENT
-                )
-            params.setTrustedOverlay()
-            params.fitInsetsTypes = 0
-            params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
-            params.token = Binder()
-            params.packageName = packageName
-            params.layoutInDisplayCutoutMode =
-                WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
-            params.privateFlags =
-                params.privateFlags or WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
-            return params
-        }
-
-        fun getFillInIntent(): Intent {
-            val fillInIntent = Intent()
-            fillInIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
-            fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
-            // FLAG_ACTIVITY_NEW_TASK is auto-applied because
-            // we're starting the FSI activity from a non-Activity context
-            return fillInIntent
-        }
-
-        fun getLaunchBounds(windowManager: WindowManager): Rect {
-            // TODO(b/243421660) check this works for non-resizeable activity
-            return Rect()
-        }
-
-        fun getActivityOptions(context: Context, windowManager: WindowManager): ActivityOptions {
-            // Custom options so there is no activity transition animation
-            val options =
-                ActivityOptions.makeCustomAnimation(context, 0 /* enterResId */, 0 /* exitResId */)
-
-            options.taskAlwaysOnTop = true
-
-            options.pendingIntentLaunchFlags =
-                Intent.FLAG_ACTIVITY_NEW_DOCUMENT or
-                    Intent.FLAG_ACTIVITY_MULTIPLE_TASK or
-                    Intent.FLAG_ACTIVITY_NEW_TASK
-
-            options.launchBounds = getLaunchBounds(windowManager)
-            return options
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
index ae19feb..9001470 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProvider.java
@@ -35,10 +35,6 @@
          */
         NO_FSI_SHOW_STICKY_HUN(false),
         /**
-         * Full screen intents are disabled.
-         */
-        NO_FSI_DISABLED(false),
-        /**
          * No full screen intent included, so there is nothing to show.
          */
         NO_FULL_SCREEN_INTENT(false),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
index 0163dbe..9f45b9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImpl.java
@@ -244,10 +244,6 @@
 
     @Override
     public FullScreenIntentDecision getFullScreenIntentDecision(NotificationEntry entry) {
-        if (mFlags.disableFsi()) {
-            return FullScreenIntentDecision.NO_FSI_DISABLED;
-        }
-
         if (entry.getSbn().getNotification().fullScreenIntent == null) {
             if (entry.isStickyAndNotDemoted()) {
                 return FullScreenIntentDecision.NO_FSI_SHOW_STICKY_HUN;
@@ -343,9 +339,6 @@
             case NO_FSI_SHOW_STICKY_HUN:
                 mLogger.logNoFullscreen(entry, "Permission denied, show sticky HUN");
                 return;
-            case NO_FSI_DISABLED:
-                mLogger.logNoFullscreen(entry, "Disabled");
-                return;
             case NO_FULL_SCREEN_INTENT:
                 return;
             case NO_FSI_SUPPRESSED_BY_DND:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 2868116..92c5b63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -211,7 +211,11 @@
                 public void onViewAttachedToWindow(View v) {
                     mConfigurationController.addCallback(mConfigurationListener);
                     mZenModeController.addCallback(mZenModeControllerCallback);
-                    mBarState = mStatusBarStateController.getState();
+                    final int newBarState = mStatusBarStateController.getState();
+                    if (newBarState != mBarState) {
+                        mStateListener.onStateChanged(newBarState);
+                        mStateListener.onStatePostChange();
+                    }
                     mStatusBarStateController.addCallback(
                             mStateListener, SysuiStatusBarStateController.RANK_STACK_SCROLLER);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index aaf9300..c6f56d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -251,13 +251,13 @@
                 || (isFastNonDismissGesture && isAbleToShowMenu);
         int menuSnapTarget = menuRow.getMenuSnapTarget();
         boolean isNonFalseMenuRevealingGesture =
-                !isFalseGesture() && isMenuRevealingGestureAwayFromMenu;
+                isMenuRevealingGestureAwayFromMenu && !isFalseGesture();
         if ((isNonDismissGestureTowardsMenu || isNonFalseMenuRevealingGesture)
                 && menuSnapTarget != 0) {
             // Menu has not been snapped to previously and this is menu revealing gesture
             snapOpen(animView, menuSnapTarget, velocity);
             menuRow.onSnapOpen();
-        } else if (isDismissGesture(ev) && !gestureTowardsMenu) {
+        } else if (isDismissGesture && !gestureTowardsMenu) {
             dismiss(animView, velocity);
             menuRow.onDismiss();
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
index 548d1a1..8b6d6a4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
@@ -25,9 +25,10 @@
     /**
      * This method looks for views that can be rounded (and implement [Roundable]) during a
      * notification swipe.
+     *
      * @return The [Roundable] targets above/below the [viewSwiped] (if available). The
-     * [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
-     * no above/below notification or the notification is not part of the same section.
+     *   [RoundableTargets.before] and [RoundableTargets.after] parameters can be `null` if there is
+     *   no above/below notification or the notification is not part of the same section.
      */
     fun findRoundableTargets(
         viewSwiped: ExpandableNotificationRow,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 9f38361..7855cdf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -374,6 +374,17 @@
     }
 
     @Override
+    public void onBiometricDetected(int userId, BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) {
+        Trace.beginSection("BiometricUnlockController#onBiometricDetected");
+        if (mUpdateMonitor.isGoingToSleep()) {
+            Trace.endSection();
+            return;
+        }
+        startWakeAndUnlock(MODE_SHOW_BOUNCER);
+    }
+
+    @Override
     public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
             boolean isStrongBiometric) {
         Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 8dcfec7..9e62817 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -375,8 +375,6 @@
     void fadeKeyguardAfterLaunchTransition(Runnable beforeFading,
             Runnable endRunnable, Runnable cancelRunnable);
 
-    void animateKeyguardUnoccluding();
-
     void startLaunchTransitionTimeout();
 
     boolean hideKeyguardImpl(boolean forceStateChange);
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 17fb055..664d61a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -104,6 +104,8 @@
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.DateTimeView;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
 import android.window.OnBackInvokedCallback;
 import android.window.OnBackInvokedDispatcher;
 
@@ -164,6 +166,7 @@
 import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
 import com.android.systemui.navigationbar.NavigationBarController;
 import com.android.systemui.navigationbar.NavigationBarView;
+import com.android.systemui.notetask.NoteTaskController;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.OverlayPlugin;
@@ -507,6 +510,7 @@
     protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
     private final BrightnessSliderController.Factory mBrightnessSliderFactory;
     private final FeatureFlags mFeatureFlags;
+    private final boolean mAnimateBack;
     private final FragmentService mFragmentService;
     private final ScreenOffAnimationController mScreenOffAnimationController;
     private final WallpaperController mWallpaperController;
@@ -642,7 +646,7 @@
     private NotificationActivityStarter mNotificationActivityStarter;
     private final Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
     private final Optional<Bubbles> mBubblesOptional;
-    private final Bubbles.BubbleExpandListener mBubbleExpandListener;
+    private final Lazy<NoteTaskController> mNoteTaskControllerLazy;
     private final Optional<StartingSurface> mStartingSurfaceOptional;
 
     private final ActivityIntentHelper mActivityIntentHelper;
@@ -653,6 +657,7 @@
 
     private final InteractionJankMonitor mJankMonitor;
 
+    /** Existing callback that handles back gesture invoked for the Shade. */
     private final OnBackInvokedCallback mOnBackInvokedCallback = () -> {
         if (DEBUG) {
             Log.d(TAG, "mOnBackInvokedCallback() called");
@@ -660,6 +665,33 @@
         onBackPressed();
     };
 
+    private boolean shouldBackBeHandled() {
+        return (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED
+                && !isBouncerShowingOverDream());
+    }
+
+    /**
+     *  New callback that handles back gesture invoked, cancel, progress
+     *  and provides feedback via Shade animation.
+     *  (enabled via the WM_SHADE_ANIMATE_BACK_GESTURE flag)
+     */
+    private final OnBackAnimationCallback mOnBackAnimationCallback = new OnBackAnimationCallback() {
+        @Override
+        public void onBackInvoked() {
+            onBackPressed();
+        }
+
+        @Override
+        public void onBackProgressed(BackEvent event) {
+            if (shouldBackBeHandled()) {
+                if (mNotificationPanelViewController.canPanelBeCollapsed()) {
+                    float fraction = event.getProgress();
+                    mNotificationPanelViewController.onBackProgressed(fraction);
+                }
+            }
+        }
+    };
+
     /**
      * Public constructor for CentralSurfaces.
      *
@@ -705,6 +737,7 @@
             WakefulnessLifecycle wakefulnessLifecycle,
             SysuiStatusBarStateController statusBarStateController,
             Optional<Bubbles> bubblesOptional,
+            Lazy<NoteTaskController> noteTaskControllerLazy,
             DeviceProvisionedController deviceProvisionedController,
             NavigationBarController navigationBarController,
             AccessibilityFloatingMenuController accessibilityFloatingMenuController,
@@ -795,6 +828,7 @@
         mWakefulnessLifecycle = wakefulnessLifecycle;
         mStatusBarStateController = statusBarStateController;
         mBubblesOptional = bubblesOptional;
+        mNoteTaskControllerLazy = noteTaskControllerLazy;
         mDeviceProvisionedController = deviceProvisionedController;
         mNavigationBarController = navigationBarController;
         mAccessibilityFloatingMenuController = accessibilityFloatingMenuController;
@@ -852,9 +886,6 @@
         mShadeExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged);
         mShadeExpansionStateManager.addFullExpansionListener(this::onShadeExpansionFullyChanged);
 
-        mBubbleExpandListener = (isExpanding, key) ->
-                mContext.getMainExecutor().execute(this::updateScrimController);
-
         mActivityIntentHelper = new ActivityIntentHelper(mContext);
         mActivityLaunchAnimator = activityLaunchAnimator;
 
@@ -882,6 +913,17 @@
         if (mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI)) {
             mContext.getApplicationInfo().setEnableOnBackInvokedCallback(true);
         }
+        // Based on teamfood flag, enable predictive back animation for the Shade.
+        mAnimateBack = mFeatureFlags.isEnabled(Flags.WM_SHADE_ANIMATE_BACK_GESTURE);
+    }
+
+    private void initBubbles(Bubbles bubbles) {
+        final Bubbles.BubbleExpandListener listener = (isExpanding, key) ->
+                mContext.getMainExecutor().execute(() -> {
+                    updateScrimController();
+                    mNoteTaskControllerLazy.get().onBubbleExpandChanged(isExpanding, key);
+                });
+        bubbles.setExpandListener(listener);
     }
 
     @Override
@@ -889,9 +931,7 @@
         mScreenLifecycle.addObserver(mScreenObserver);
         mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
-        if (mBubblesOptional.isPresent()) {
-            mBubblesOptional.get().setExpandListener(mBubbleExpandListener);
-        }
+        mBubblesOptional.ifPresent(this::initBubbles);
 
         // Do not restart System UI when the bugreport flag changes.
         mFeatureFlags.addListener(Flags.LEAVE_SHADE_OPEN_FOR_BUGREPORT, event -> {
@@ -2214,10 +2254,10 @@
             pw.println("Current Status Bar state:");
             pw.println("  mExpandedVisible=" + mShadeController.isExpandedVisible());
             pw.println("  mDisplayMetrics=" + mDisplayMetrics);
-            pw.println("  mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
-            pw.println("  mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller)
-                    + " scroll " + mStackScroller.getScrollX()
+            pw.print("  mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
+            pw.print(" scroll " + mStackScroller.getScrollX()
                     + "," + mStackScroller.getScrollY());
+            pw.println(" translationX " + mStackScroller.getTranslationX());
         }
 
         pw.print("  mInteractingWindows="); pw.println(mInteractingWindows);
@@ -2554,7 +2594,7 @@
             String action = intent.getAction();
             String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
             if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
-                if (mIsShortcutListSearchEnabled && Utilities.isTablet(mContext)) {
+                if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(mContext)) {
                     KeyboardShortcutListSearch.dismiss();
                 } else {
                     KeyboardShortcuts.dismiss();
@@ -2699,7 +2739,8 @@
                 if (viewRootImpl != null) {
                     viewRootImpl.getOnBackInvokedDispatcher()
                             .registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT,
-                                    mOnBackInvokedCallback);
+                                    mAnimateBack ? mOnBackAnimationCallback
+                                            : mOnBackInvokedCallback);
                     mIsBackCallbackRegistered = true;
                     if (DEBUG) Log.d(TAG, "is now VISIBLE to user AND callback registered");
                 }
@@ -2714,7 +2755,9 @@
                 ViewRootImpl viewRootImpl = getViewRootImpl();
                 if (viewRootImpl != null) {
                     viewRootImpl.getOnBackInvokedDispatcher()
-                            .unregisterOnBackInvokedCallback(mOnBackInvokedCallback);
+                            .unregisterOnBackInvokedCallback(
+                                    mAnimateBack ? mOnBackAnimationCallback
+                                            : mOnBackInvokedCallback);
                     mIsBackCallbackRegistered = false;
                     if (DEBUG) Log.d(TAG, "is NOT VISIBLE to user, AND callback unregistered");
                 }
@@ -2991,16 +3034,6 @@
     }
 
     /**
-     * Plays the animation when an activity that was occluding Keyguard goes away.
-     */
-    @Override
-    public void animateKeyguardUnoccluding() {
-        mNotificationPanelViewController.setExpandedFraction(0f);
-        mCommandQueueCallbacks.animateExpandNotificationsPanel();
-        mScrimController.setUnocclusionAnimationRunning(true);
-    }
-
-    /**
      * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
      * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
      * because the launched app crashed or something else went wrong.
@@ -3256,9 +3289,10 @@
         if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) {
             return true;
         }
-        if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED
-                && !isBouncerShowingOverDream()) {
+        if (shouldBackBeHandled()) {
             if (mNotificationPanelViewController.canPanelBeCollapsed()) {
+                // this is the Shade dismiss animation, so make sure QQS closes when it ends.
+                mNotificationPanelViewController.onBackPressed();
                 mShadeController.animateCollapseShade();
             }
             return true;
@@ -3713,6 +3747,12 @@
     @Override
     public void notifyBiometricAuthModeChanged() {
         mDozeServiceHost.updateDozing();
+        if (mBiometricUnlockController.getMode()
+                == BiometricUnlockController.MODE_DISMISS_BOUNCER) {
+            // Don't update the scrim controller at this time, in favor of the transition repository
+            // updating the scrim
+            return;
+        }
         updateScrimController();
     }
 
@@ -3765,6 +3805,9 @@
             } else {
                 mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
             }
+            // This will cancel the keyguardFadingAway animation if it is running. We need to do
+            // this as otherwise it can remain pending and leave keyguard in a weird state.
+            mUnlockScrimCallback.onCancelled();
         } else if (mBouncerShowing && !unlocking) {
             // Bouncer needs the front scrim when it's on top of an activity,
             // tapping on a notification, editing QS or being dismissed by
@@ -3905,7 +3948,7 @@
     }
 
     protected void toggleKeyboardShortcuts(int deviceId) {
-        if (mIsShortcutListSearchEnabled && Utilities.isTablet(mContext)) {
+        if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(mContext)) {
             KeyboardShortcutListSearch.toggle(mContext, deviceId);
         } else {
             KeyboardShortcuts.toggle(mContext, deviceId);
@@ -3913,7 +3956,7 @@
     }
 
     protected void dismissKeyboardShortcuts() {
-        if (mIsShortcutListSearchEnabled && Utilities.isTablet(mContext)) {
+        if (mIsShortcutListSearchEnabled && Utilities.isLargeScreen(mContext)) {
             KeyboardShortcutListSearch.dismiss();
         } else {
             KeyboardShortcuts.dismiss();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6c532a5..e6b76ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -22,8 +22,6 @@
 import android.app.ActivityTaskManager;
 import android.app.AlarmManager;
 import android.app.AlarmManager.AlarmClockInfo;
-import android.app.IActivityManager;
-import android.app.SynchronousUserSwitchObserver;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -134,7 +132,6 @@
     private final NextAlarmController mNextAlarmController;
     private final AlarmManager mAlarmManager;
     private final UserInfoController mUserInfoController;
-    private final IActivityManager mIActivityManager;
     private final UserManager mUserManager;
     private final UserTracker mUserTracker;
     private final DevicePolicyManager mDevicePolicyManager;
@@ -149,6 +146,7 @@
     private final KeyguardStateController mKeyguardStateController;
     private final LocationController mLocationController;
     private final PrivacyItemController mPrivacyItemController;
+    private final Executor mMainExecutor;
     private final Executor mUiBgExecutor;
     private final SensorPrivacyController mSensorPrivacyController;
     private final RecordingController mRecordingController;
@@ -168,16 +166,17 @@
     @Inject
     public PhoneStatusBarPolicy(StatusBarIconController iconController,
             CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher,
-            @UiBackground Executor uiBgExecutor, @Main Looper looper, @Main Resources resources,
-            CastController castController, HotspotController hotspotController,
-            BluetoothController bluetoothController, NextAlarmController nextAlarmController,
-            UserInfoController userInfoController, RotationLockController rotationLockController,
-            DataSaverController dataSaverController, ZenModeController zenModeController,
+            @Main Executor mainExecutor, @UiBackground Executor uiBgExecutor, @Main Looper looper,
+            @Main Resources resources, CastController castController,
+            HotspotController hotspotController, BluetoothController bluetoothController,
+            NextAlarmController nextAlarmController, UserInfoController userInfoController,
+            RotationLockController rotationLockController, DataSaverController dataSaverController,
+            ZenModeController zenModeController,
             DeviceProvisionedController deviceProvisionedController,
             KeyguardStateController keyguardStateController,
             LocationController locationController,
-            SensorPrivacyController sensorPrivacyController, IActivityManager iActivityManager,
-            AlarmManager alarmManager, UserManager userManager, UserTracker userTracker,
+            SensorPrivacyController sensorPrivacyController, AlarmManager alarmManager,
+            UserManager userManager, UserTracker userTracker,
             DevicePolicyManager devicePolicyManager, RecordingController recordingController,
             @Nullable TelecomManager telecomManager, @DisplayId int displayId,
             @Main SharedPreferences sharedPreferences, DateFormatUtil dateFormatUtil,
@@ -195,7 +194,6 @@
         mNextAlarmController = nextAlarmController;
         mAlarmManager = alarmManager;
         mUserInfoController = userInfoController;
-        mIActivityManager = iActivityManager;
         mUserManager = userManager;
         mUserTracker = userTracker;
         mDevicePolicyManager = devicePolicyManager;
@@ -208,6 +206,7 @@
         mPrivacyItemController = privacyItemController;
         mSensorPrivacyController = sensorPrivacyController;
         mRecordingController = recordingController;
+        mMainExecutor = mainExecutor;
         mUiBgExecutor = uiBgExecutor;
         mTelecomManager = telecomManager;
         mRingerModeTracker = ringerModeTracker;
@@ -256,11 +255,7 @@
         mRingerModeTracker.getRingerModeInternal().observeForever(observer);
 
         // listen for user / profile change.
-        try {
-            mIActivityManager.registerUserSwitchObserver(mUserSwitchListener, TAG);
-        } catch (RemoteException e) {
-            // Ignore
-        }
+        mUserTracker.addCallback(mUserSwitchListener, mMainExecutor);
 
         // TTY status
         updateTTY();
@@ -555,15 +550,15 @@
         });
     }
 
-    private final SynchronousUserSwitchObserver mUserSwitchListener =
-            new SynchronousUserSwitchObserver() {
+    private final UserTracker.Callback mUserSwitchListener =
+            new UserTracker.Callback() {
                 @Override
-                public void onUserSwitching(int newUserId) throws RemoteException {
+                public void onUserChanging(int newUser, Context userContext) {
                     mHandler.post(() -> mUserInfoController.reloadUserInfo());
                 }
 
                 @Override
-                public void onUserSwitchComplete(int newUserId) throws RemoteException {
+                public void onUserChanged(int newUser, Context userContext) {
                     mHandler.post(() -> {
                         updateAlarm();
                         updateManagedProfile();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 80093a3..ce650d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
+
 import static java.lang.Float.isNaN;
 
 import android.animation.Animator;
@@ -53,7 +55,11 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
+import com.android.systemui.keyguard.shared.model.TransitionState;
+import com.android.systemui.keyguard.shared.model.TransitionStep;
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
 import com.android.systemui.scrim.ScrimView;
 import com.android.systemui.shade.NotificationPanelViewController;
 import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -71,6 +77,8 @@
 
 import javax.inject.Inject;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+
 /**
  * Controls both the scrim behind the notifications and in front of the notifications (when a
  * security method gets shown).
@@ -138,26 +146,12 @@
     private boolean mTransitioningToFullShade;
 
     /**
-     * Is there currently an unocclusion animation running. Used to avoid bright flickers
-     * of the notification scrim.
-     */
-    private boolean mUnOcclusionAnimationRunning;
-
-    /**
      * The percentage of the bouncer which is hidden. If 1, the bouncer is completely hidden. If
      * 0, the bouncer is visible.
      */
     @FloatRange(from = 0, to = 1)
     private float mBouncerHiddenFraction = KeyguardBouncerConstants.EXPANSION_HIDDEN;
 
-    /**
-     * Set whether an unocclusion animation is currently running on the notification panel. Used
-     * to avoid bright flickers of the notification scrim.
-     */
-    public void setUnocclusionAnimationRunning(boolean unocclusionAnimationRunning) {
-        mUnOcclusionAnimationRunning = unocclusionAnimationRunning;
-    }
-
     @IntDef(prefix = {"VISIBILITY_"}, value = {
             TRANSPARENT,
             SEMI_TRANSPARENT,
@@ -265,6 +259,28 @@
     private boolean mWakeLockHeld;
     private boolean mKeyguardOccluded;
 
+    private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+    private CoroutineDispatcher mMainDispatcher;
+    private boolean mIsBouncerToGoneTransitionStarted = false;
+    private boolean mIsBouncerToGoneTransitionRunning = false;
+    private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
+    private final Consumer<Float> mScrimAlphaConsumer =
+            (Float alpha) -> {
+                mScrimInFront.setViewAlpha(0f);
+                mNotificationsScrim.setViewAlpha(0f);
+                mScrimBehind.setViewAlpha(alpha);
+            };
+    final Consumer<TransitionStep> mPrimaryBouncerToGoneTransition =
+            (TransitionStep step) -> {
+                mIsBouncerToGoneTransitionRunning =
+                    step.getTransitionState() == TransitionState.RUNNING;
+                mIsBouncerToGoneTransitionStarted =
+                    step.getTransitionState() == TransitionState.STARTED;
+                if (mIsBouncerToGoneTransitionStarted) {
+                    transitionTo(ScrimState.UNLOCKED);
+                }
+            };
+
     @Inject
     public ScrimController(
             LightBarController lightBarController,
@@ -279,7 +295,10 @@
             @Main Executor mainExecutor,
             ScreenOffAnimationController screenOffAnimationController,
             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
-            StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+            PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
+            KeyguardTransitionInteractor keyguardTransitionInteractor,
+            @Main CoroutineDispatcher mainDispatcher) {
         mScrimStateListener = lightBarController::setScrimState;
         mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
 
@@ -318,6 +337,9 @@
             }
         });
         mColors = new GradientColors();
+        mPrimaryBouncerToGoneTransitionViewModel = primaryBouncerToGoneTransitionViewModel;
+        mKeyguardTransitionInteractor = keyguardTransitionInteractor;
+        mMainDispatcher = mainDispatcher;
     }
 
     /**
@@ -357,11 +379,23 @@
         for (ScrimState state : ScrimState.values()) {
             state.prepare(state);
         }
+
+        collectFlow(behindScrim, mKeyguardTransitionInteractor.getPrimaryBouncerToGoneTransition(),
+                mPrimaryBouncerToGoneTransition, mMainDispatcher);
+        collectFlow(behindScrim, mPrimaryBouncerToGoneTransitionViewModel.getScrimAlpha(),
+                mScrimAlphaConsumer, mMainDispatcher);
     }
 
-    /**
-     * Sets corner radius of scrims.
-     */
+    // TODO(b/270984686) recompute scrim height accurately, based on shade contents.
+    /** Set corner radius of the bottom edge of the Notification scrim. */
+    public void setNotificationBottomRadius(float radius) {
+        if (mNotificationsScrim == null) {
+            return;
+        }
+        mNotificationsScrim.setBottomEdgeRadius(radius);
+    }
+
+    /** Sets corner radius of scrims. */
     public void setScrimCornerRadius(int radius) {
         if (mScrimBehind == null || mNotificationsScrim == null) {
             return;
@@ -379,6 +413,11 @@
     }
 
     public void transitionTo(ScrimState state, Callback callback) {
+        if (mIsBouncerToGoneTransitionRunning) {
+            Log.i(TAG, "Skipping transition to: " + state
+                    + " while mIsBouncerToGoneTransitionRunning");
+            return;
+        }
         if (state == mState) {
             // Call the callback anyway, unless it's already enqueued
             if (callback != null && mCallback != callback) {
@@ -525,6 +564,12 @@
         scheduleUpdate();
     }
 
+    /** This is used by the predictive back gesture animation to scale the Shade. */
+    public void applyBackScaling(float scale) {
+        mNotificationsScrim.setScaleX(scale);
+        mNotificationsScrim.setScaleY(scale);
+    }
+
     public void onTrackingStarted() {
         mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen();
         if (!mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) {
@@ -532,10 +577,6 @@
         }
     }
 
-    public void onExpandingFinished() {
-        setUnocclusionAnimationRunning(false);
-    }
-
     @VisibleForTesting
     protected void onHideWallpaperTimeout() {
         if (mState != ScrimState.AOD && mState != ScrimState.PULSING) {
@@ -802,10 +843,11 @@
                         mBehindAlpha = 0;
                         mNotificationsAlpha = 0;
                     } else {
-                        // Behind scrim will finish fading in at 30% expansion.
                         float behindFraction = MathUtils
                                 .constrainedMap(0f, 1f, 0f, 0.3f, mPanelExpansionFraction);
-                        mBehindAlpha = behindFraction * mDefaultScrimAlpha;
+                        if (!mIsBouncerToGoneTransitionStarted) {
+                            mBehindAlpha = behindFraction * mDefaultScrimAlpha;
+                        }
                         // Delay fade-in of notification scrim a bit further, to coincide with the
                         // behind scrim finishing fading in.
                         // Also to coincide with the view starting to fade in, otherwise the empty
@@ -875,13 +917,6 @@
             if (mKeyguardOccluded || hideNotificationScrim) {
                 mNotificationsAlpha = 0;
             }
-            if (mUnOcclusionAnimationRunning && mState == ScrimState.KEYGUARD) {
-                // We're unoccluding the keyguard and don't want to have a bright flash.
-                mNotificationsAlpha = ScrimState.KEYGUARD.getNotifAlpha();
-                mNotificationsTint = ScrimState.KEYGUARD.getNotifTint();
-                mBehindAlpha = ScrimState.KEYGUARD.getBehindAlpha();
-                mBehindTint = ScrimState.KEYGUARD.getBehindTint();
-            }
         }
         if (mState != ScrimState.UNLOCKED) {
             mAnimatingPanelExpansionOnUnlock = false;
@@ -1150,7 +1185,9 @@
             Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_tint",
                     Color.alpha(tint));
             scrimView.setTint(tint);
-            scrimView.setViewAlpha(alpha);
+            if (!mIsBouncerToGoneTransitionRunning) {
+                scrimView.setViewAlpha(alpha);
+            }
         } else {
             scrim.setAlpha(alpha);
         }
@@ -1498,6 +1535,9 @@
     }
 
     public void setKeyguardOccluded(boolean keyguardOccluded) {
+        if (mKeyguardOccluded == keyguardOccluded) {
+            return;
+        }
         mKeyguardOccluded = keyguardOccluded;
         updateScrims();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index a127139..66f5b65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -281,7 +281,6 @@
     private float mQsExpansion;
     final Set<KeyguardViewManagerCallback> mCallbacks = new HashSet<>();
     private boolean mIsModernAlternateBouncerEnabled;
-    private boolean mIsUnoccludeTransitionFlagEnabled;
     private boolean mIsBackAnimationEnabled;
 
     private OnDismissAction mAfterKeyguardGoneAction;
@@ -361,7 +360,6 @@
                 .map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
         mIsModernAlternateBouncerEnabled = featureFlags.isEnabled(Flags.MODERN_ALTERNATE_BOUNCER);
         mAlternateBouncerInteractor = alternateBouncerInteractor;
-        mIsUnoccludeTransitionFlagEnabled = featureFlags.isEnabled(Flags.UNOCCLUSION_TRANSITION);
         mIsBackAnimationEnabled =
                 featureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM);
     }
@@ -880,11 +878,6 @@
             // by a FLAG_DISMISS_KEYGUARD_ACTIVITY.
             reset(isOccluding /* hideBouncerWhenShowing*/);
         }
-        if (!mIsUnoccludeTransitionFlagEnabled) {
-            if (animate && !isOccluded && isShowing && !primaryBouncerIsShowing()) {
-                mCentralSurfaces.animateKeyguardUnoccluding();
-            }
-        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 3471a46..726b234 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -561,10 +561,6 @@
             mLogger.logFullScreenIntentSuppressedByVR(entry);
             return;
         }
-        if (mFeatureFlags.isEnabled(Flags.FSI_CHROME)) {
-            // FsiChromeRepo runs its own implementation of launchFullScreenIntent
-            return;
-        }
         // Stop screensaver if the notification has a fullscreen intent.
         // (like an incoming phone call)
         mUiBgExecutor.execute(() -> {
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
index 8c82fba..f4e3eab 100644
--- 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
@@ -45,7 +45,7 @@
  * 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
+ *    updated when a new carrier config comes down
  */
 class SystemUiCarrierConfig
 internal constructor(
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 b3d5b1e..53a208c 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
@@ -353,8 +353,8 @@
      * True if the checked subId is in the list of current subs or the active mobile data subId
      *
      * @param checkedSubs the list to validate [subId] against. To invalidate the cache, pass in the
-     * new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
-     * current known subscriptions
+     *   new subscription list. Otherwise use [subscriptions.value] to validate a subId against the
+     *   current known subscriptions
      */
     private fun checkSub(subId: Int, checkedSubs: List<SubscriptionModel>): Boolean {
         if (activeMobileDataSubscriptionId.value == subId) return true
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 7b0f952..4caf2b0 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
@@ -92,7 +92,8 @@
      * 1. The default network name, if one is configured
      * 2. A derived name based off of the intent [ACTION_SERVICE_PROVIDERS_UPDATED]
      * 3. Or, in the case where the repository sends us the default network name, we check for an
-     * override in [connectionInfo.operatorAlphaShort], a value that is derived from [ServiceState]
+     *    override in [connectionInfo.operatorAlphaShort], a value that is derived from
+     *    [ServiceState]
      */
     val networkName: StateFlow<NetworkNameModel>
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
index 24cd930..8e103f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/LocationBasedMobileViewModel.kt
@@ -25,7 +25,7 @@
  * allows the mobile icon to change some view parameters at different locations
  *
  * @param commonImpl for convenience, this class wraps a base interface that can provides all of the
- * common implementations between locations. See [MobileIconViewModel]
+ *   common implementations between locations. See [MobileIconViewModel]
  */
 abstract class LocationBasedMobileViewModel(
     val commonImpl: MobileIconViewModelCommon,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
index e0e0ed7..b129617 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcher.kt
@@ -41,7 +41,6 @@
  * or the [WifiRepositoryImpl]'s prod implementation, based on the current demo mode value. In this
  * way, downstream clients can all consist of real implementations and not care about which
  * repository is responsible for the data. Graphically:
- *
  * ```
  * RealRepository
  *                 │
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
index bdb656b..1e223b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.kt
@@ -146,7 +146,7 @@
      *
      * @param guestUserId id of the guest user to remove
      * @param targetUserId id of the user to switch to after guest is removed. If
-     * `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
+     *   `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
      */
     fun removeGuestUser(guestUserId: Int, targetUserId: Int) {
         userInteractor.removeGuestUser(
@@ -160,9 +160,9 @@
      *
      * @param guestUserId user id of the guest user to exit
      * @param targetUserId user id of the guest user to exit, set to UserHandle#USER_NULL when
-     * target user id is not known
+     *   target user id is not known
      * @param forceRemoveGuestOnExit true: remove guest before switching user, false: remove guest
-     * only if its ephemeral, else keep guest
+     *   only if its ephemeral, else keep guest
      */
     fun exitGuestUser(guestUserId: Int, targetUserId: Int, forceRemoveGuestOnExit: Boolean) {
         userInteractor.exitGuestUser(guestUserId, targetUserId, forceRemoveGuestOnExit)
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
index 462504e..4e27ce6 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusManager.kt
@@ -82,6 +82,8 @@
     fun startListener() {
         handler.post {
             if (hasStarted) return@post
+            logDebug { "Listener has started." }
+
             hasStarted = true
             isInUsiSession =
                 inputManager.hasInputDevice {
@@ -116,6 +118,10 @@
 
         val device: InputDevice = inputManager.getInputDevice(deviceId) ?: return
         if (!device.supportsSource(InputDevice.SOURCE_STYLUS)) return
+        logDebug {
+            "Stylus InputDevice added: $deviceId ${device.name}, " +
+                "External: ${device.isExternal}"
+        }
 
         if (!device.isExternal) {
             registerBatteryListener(deviceId)
@@ -137,6 +143,7 @@
 
         val device: InputDevice = inputManager.getInputDevice(deviceId) ?: return
         if (!device.supportsSource(InputDevice.SOURCE_STYLUS)) return
+        logDebug { "Stylus InputDevice changed: $deviceId ${device.name}" }
 
         val currAddress: String? = device.bluetoothAddress
         val prevAddress: String? = inputDeviceAddressMap[deviceId]
@@ -157,6 +164,8 @@
         if (!hasStarted) return
 
         if (!inputDeviceAddressMap.contains(deviceId)) return
+        logDebug { "Stylus InputDevice removed: $deviceId" }
+
         unregisterBatteryListener(deviceId)
 
         val btAddress: String? = inputDeviceAddressMap[deviceId]
@@ -180,6 +189,11 @@
 
             val isCharging = String(value) == "true"
 
+            logDebug {
+                "Charging state metadata changed for device $inputDeviceId " +
+                    "${device.address}: $isCharging"
+            }
+
             executeStylusBatteryCallbacks { cb ->
                 cb.onStylusBluetoothChargingStateChanged(inputDeviceId, device, isCharging)
             }
@@ -194,13 +208,10 @@
         handler.post {
             if (!hasStarted) return@post
 
-            if (DEBUG) {
-                Log.d(
-                    TAG,
-                    "onBatteryStateChanged for $deviceId. " +
-                        "batteryState present: ${batteryState.isPresent}, " +
-                        "capacity: ${batteryState.capacity}"
-                )
+            logDebug {
+                "Battery state changed for $deviceId. " +
+                    "batteryState present: ${batteryState.isPresent}, " +
+                    "capacity: ${batteryState.capacity}"
             }
 
             val batteryStateValid = isBatteryStateValid(batteryState)
@@ -216,7 +227,7 @@
     }
 
     private fun onStylusBluetoothConnected(deviceId: Int, btAddress: String) {
-        trackAndLogBluetoothSession(deviceId, true)
+        trackAndLogBluetoothSession(deviceId, btAddress, true)
         val device: BluetoothDevice = bluetoothAdapter?.getRemoteDevice(btAddress) ?: return
         try {
             bluetoothAdapter.addOnMetadataChangedListener(device, executor, this)
@@ -226,7 +237,7 @@
     }
 
     private fun onStylusBluetoothDisconnected(deviceId: Int, btAddress: String) {
-        trackAndLogBluetoothSession(deviceId, false)
+        trackAndLogBluetoothSession(deviceId, btAddress, false)
         val device: BluetoothDevice = bluetoothAdapter?.getRemoteDevice(btAddress) ?: return
         try {
             bluetoothAdapter.removeOnMetadataChangedListener(device, this)
@@ -245,6 +256,7 @@
         if (!featureFlags.isEnabled(Flags.TRACK_STYLUS_EVER_USED)) return
         if (InputSettings.isStylusEverUsed(context)) return
 
+        logDebug { "Stylus used for the first time." }
         InputSettings.setStylusEverUsed(context, true)
         executeStylusCallbacks { cb -> cb.onStylusFirstUsed() }
     }
@@ -259,12 +271,7 @@
         // TODO(b/268618918) handle cases where an invalid battery callback from a previous stylus
         //  is sent after the actual valid callback
         if (batteryStateValid && usiSessionId == null) {
-            if (DEBUG) {
-                Log.d(
-                    TAG,
-                    "USI battery newly present, entering new USI session. Device ID: $deviceId"
-                )
-            }
+            logDebug { "USI battery newly present, entering new USI session: $deviceId" }
             usiSessionId = instanceIdSequence.newInstanceId()
             uiEventLogger.logWithInstanceId(
                 StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_FIRST_DETECTED,
@@ -273,9 +280,7 @@
                 usiSessionId
             )
         } else if (!batteryStateValid && usiSessionId != null) {
-            if (DEBUG) {
-                Log.d(TAG, "USI battery newly absent, exiting USI session Device ID: $deviceId")
-            }
+            logDebug { "USI battery newly absent, exiting USI session: $deviceId" }
             uiEventLogger.logWithInstanceId(
                 StylusUiEvent.USI_STYLUS_BATTERY_PRESENCE_REMOVED,
                 0,
@@ -286,8 +291,17 @@
         }
     }
 
-    private fun trackAndLogBluetoothSession(deviceId: Int, bluetoothConnected: Boolean) {
-        if (bluetoothConnected) {
+    private fun trackAndLogBluetoothSession(
+        deviceId: Int,
+        btAddress: String,
+        btConnected: Boolean
+    ) {
+        logDebug {
+            "Bluetooth stylus ${if (btConnected) "connected" else "disconnected"}:" +
+                " $deviceId $btAddress"
+        }
+
+        if (btConnected) {
             inputDeviceBtSessionIdMap[deviceId] = instanceIdSequence.newInstanceId()
             uiEventLogger.logWithInstanceId(
                 StylusUiEvent.BLUETOOTH_STYLUS_CONNECTED,
@@ -383,7 +397,13 @@
     }
 
     companion object {
-        private val TAG = StylusManager::class.simpleName.orEmpty()
-        private val DEBUG = false
+        val TAG = StylusManager::class.simpleName.orEmpty()
+        const val DEBUG = false
+    }
+}
+
+private inline fun logDebug(message: () -> String) {
+    if (StylusManager.DEBUG) {
+        Log.d(StylusManager.TAG, message())
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
index ec0a6e7..21b0efa 100644
--- a/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
+++ b/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt
@@ -26,6 +26,7 @@
 import android.content.IntentFilter
 import android.hardware.BatteryState
 import android.hardware.input.InputManager
+import android.os.Build
 import android.os.Bundle
 import android.os.Handler
 import android.os.UserHandle
@@ -109,6 +110,10 @@
 
             inputDeviceId = deviceId
             batteryCapacity = batteryState.capacity
+            logDebug {
+                "Updating notification battery state to $batteryCapacity " +
+                    "for InputDevice $deviceId."
+            }
             refresh()
         }
     }
@@ -125,12 +130,14 @@
         handler.post updateSuppressed@{
             if (suppressed == suppress) return@updateSuppressed
 
+            logDebug { "Updating notification suppression to $suppress." }
             suppressed = suppress
             refresh()
         }
     }
 
     private fun hideNotification() {
+        logDebug { "Cancelling USI low battery notification." }
         instanceId = null
         notificationManager.cancel(USI_NOTIFICATION_ID)
     }
@@ -153,6 +160,7 @@
                 .setAutoCancel(true)
                 .build()
 
+        logDebug { "Show or update USI low battery notification at $batteryCapacity." }
         logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_SHOWN)
         notificationManager.notify(USI_NOTIFICATION_ID, notification)
     }
@@ -180,10 +188,12 @@
             override fun onReceive(context: Context, intent: Intent) {
                 when (intent.action) {
                     ACTION_DISMISSED_LOW_BATTERY -> {
+                        logDebug { "USI low battery notification dismissed." }
                         logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_DISMISSED)
                         updateSuppression(true)
                     }
                     ACTION_CLICKED_LOW_BATTERY -> {
+                        logDebug { "USI low battery notification clicked." }
                         logUiEvent(StylusUiEvent.STYLUS_LOW_BATTERY_NOTIFICATION_CLICKED)
                         updateSuppression(true)
                         if (inputDeviceId == null) return
@@ -233,6 +243,8 @@
     }
 
     companion object {
+        val TAG = StylusUsiPowerUI::class.simpleName.orEmpty()
+
         // Low battery threshold matches CrOS, see:
         // https://source.chromium.org/chromium/chromium/src/+/main:ash/system/power/peripheral_battery_notifier.cc;l=41
         private const val LOW_BATTERY_THRESHOLD = 0.16f
@@ -251,3 +263,9 @@
         @VisibleForTesting const val KEY_SETTINGS_FRAGMENT_ARGS = ":settings:show_fragment_args"
     }
 }
+
+private inline fun logDebug(message: () -> String) {
+    if (Build.IS_DEBUGGABLE) {
+        Log.d(StylusUsiPowerUI.TAG, message())
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
index 60241a9..cf0184f 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TouchableRegionViewController.kt
@@ -27,7 +27,7 @@
  * pass through to the window below.
  *
  * @param touchableRegionSetter a function that, given the view and an out rect, fills the rect with
- * the touchable region of this view.
+ *   the touchable region of this view.
  */
 class TouchableRegionViewController(
     view: View,
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
index 01a81de..1612388 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarAnimator.kt
@@ -35,7 +35,7 @@
      * 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.
+     *   run for any reason.
      *
      * See [ViewHierarchyAnimator.animateAddition].
      */
@@ -55,7 +55,7 @@
      * 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.
+     *   run for any reason.
      *
      * See [ViewHierarchyAnimator.animateRemoval].
      */
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
index fe46318..125cc76 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarInfo.kt
@@ -28,10 +28,10 @@
  * A container for all the state needed to display a chipbar via [ChipbarCoordinator].
  *
  * @property startIcon the icon to display at the start of the chipbar (on the left in LTR locales;
- * on the right in RTL locales).
+ *   on the right in RTL locales).
  * @property text the text to display.
  * @property endItem an optional end item to display at the end of the chipbar (on the right in LTR
- * locales; on the left in RTL locales).
+ *   locales; on the left in RTL locales).
  * @property vibrationEffect an optional vibration effect when the chipbar is displayed
  * @property allowSwipeToDismiss true if users are allowed to swipe up to dismiss this chipbar.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
index 2683971..981f429 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldStateLoggingProviderImpl.kt
@@ -61,8 +61,6 @@
         foldStateProvider.stop()
     }
 
-    override fun onHingeAngleUpdate(angle: Float) {}
-
     override fun onFoldUpdate(@FoldUpdate update: Int) {
         val now = clock.elapsedRealtime()
         when (update) {
@@ -77,6 +75,10 @@
         }
     }
 
+    override fun onUnfoldedScreenAvailable() {
+        Log.d(TAG, "Unfolded screen available")
+    }
+
     private fun dispatchState(@LoggedFoldedStates current: Int) {
         val now = clock.elapsedRealtime()
         val previous = lastState
diff --git a/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt b/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
index 5f89d5d..9304a46 100644
--- a/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
@@ -45,7 +45,7 @@
      *
      * @param successCallback is called when the user creation is successful.
      * @param errorCallback is called when userManager.createUser returns null. (Exceptions are not
-     * handled by this class)
+     *   handled by this class)
      */
     fun createUser(
         userName: String?,
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 70523bb..a0b56aa 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,11 +17,8 @@
 
 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
@@ -121,7 +118,6 @@
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val globalSettings: GlobalSettings,
     private val tracker: UserTracker,
-    private val activityManager: IActivityManager,
     featureFlags: FeatureFlags,
 ) : UserRepository {
 
@@ -213,18 +209,18 @@
     private fun observeUserSwitching() {
         conflatedCallbackFlow {
                 val callback =
-                    object : UserSwitchObserver() {
-                        override fun onUserSwitching(newUserId: Int, reply: IRemoteCallback) {
+                    object : UserTracker.Callback {
+                        override fun onUserChanging(newUser: Int, userContext: Context) {
                             trySendWithFailureLogging(true, TAG, "userSwitching started")
                         }
 
-                        override fun onUserSwitchComplete(newUserId: Int) {
+                        override fun onUserChanged(newUserId: Int, userContext: Context) {
                             trySendWithFailureLogging(false, TAG, "userSwitching completed")
                         }
                     }
-                activityManager.registerUserSwitchObserver(callback, TAG)
+                tracker.addCallback(callback, mainDispatcher.asExecutor())
                 trySendWithFailureLogging(false, TAG, "initial value defaulting to false")
-                awaitClose { activityManager.unregisterUserSwitchObserver(callback) }
+                awaitClose { tracker.removeCallback(callback) }
             }
             .onEach { _isUserSwitchingInProgress.value = it }
             // TODO (b/262838215), Make this stateIn and initialize directly in field declaration
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 2f63f32..f026f0f 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
@@ -313,7 +313,7 @@
      * to create a new one.
      *
      * @return The multi-user user ID of the newly created guest user, or [UserHandle.USER_NULL] if
-     * the guest couldn't be created.
+     *   the guest couldn't be created.
      */
     @UserIdInt
     private suspend fun createInBackground(): Int {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
index 082c8cc..13b3b1a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
@@ -18,8 +18,10 @@
 
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
+import android.view.View
 import android.view.inputmethod.InputMethodManager
 import android.widget.EditText
+import android.widget.ImageView
 import androidx.test.filters.SmallTest
 import com.android.internal.util.LatencyTracker
 import com.android.internal.widget.LockPatternUtils
@@ -30,6 +32,7 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.Mock
@@ -37,6 +40,7 @@
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when`
+import org.mockito.Mockito.mock
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -76,7 +80,9 @@
     Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry))
         .thenReturn(passwordEntry)
     `when`(keyguardPasswordView.resources).thenReturn(context.resources)
-    keyguardPasswordViewController =
+    `when`(keyguardPasswordView.findViewById<ImageView>(R.id.switch_ime_button))
+        .thenReturn(mock(ImageView::class.java))
+     keyguardPasswordViewController =
         KeyguardPasswordViewController(
             keyguardPasswordView,
             keyguardUpdateMonitor,
@@ -113,6 +119,18 @@
   }
 
   @Test
+  fun onApplyWindowInsetsListener_onApplyWindowInsets() {
+      `when`(keyguardViewController.isBouncerShowing).thenReturn(false)
+      val argumentCaptor = ArgumentCaptor.forClass(View.OnApplyWindowInsetsListener::class.java)
+
+      keyguardPasswordViewController.onViewAttached()
+      verify(keyguardPasswordView).setOnApplyWindowInsetsListener(argumentCaptor.capture())
+      argumentCaptor.value.onApplyWindowInsets(keyguardPasswordView, null)
+
+      verify(keyguardPasswordView).hideKeyboard()
+  }
+
+  @Test
   fun testHideKeyboardWhenOnPause() {
     keyguardPasswordViewController.onPause()
     keyguardPasswordView.post {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index dfad15d..7144914 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -26,7 +26,6 @@
 
 import com.android.keyguard.logging.KeyguardLogger;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.ClockAnimations;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
@@ -61,8 +60,6 @@
     @Mock
     DozeParameters mDozeParameters;
     @Mock
-    FeatureFlags mFeatureFlags;
-    @Mock
     ScreenOffAnimationController mScreenOffAnimationController;
     @Captor
     private ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
@@ -83,7 +80,6 @@
                 mKeyguardUpdateMonitor,
                 mConfigurationController,
                 mDozeParameters,
-                mFeatureFlags,
                 mScreenOffAnimationController,
                 mKeyguardLogger);
     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 395eb8f..bd77c32 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -20,6 +20,8 @@
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
+import static android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN;
+import static android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_STARTED_WAKING_UP;
 import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
 import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
 import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
@@ -29,7 +31,6 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
 import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
 import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
-import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING;
 import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
 import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
 import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
@@ -58,8 +59,6 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.IActivityManager;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.IStrongAuthTracker;
 import android.app.trust.TrustManager;
@@ -81,6 +80,7 @@
 import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
 import android.hardware.biometrics.SensorProperties;
+import android.hardware.face.FaceAuthenticateOptions;
 import android.hardware.face.FaceManager;
 import android.hardware.face.FaceSensorProperties;
 import android.hardware.face.FaceSensorPropertiesInternal;
@@ -96,7 +96,6 @@
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.Handler;
-import android.os.IRemoteCallback;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -155,6 +154,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -238,8 +238,6 @@
     @Mock
     private KeyguardUpdateMonitorLogger mKeyguardUpdateMonitorLogger;
     @Mock
-    private IActivityManager mActivityService;
-    @Mock
     private SessionTracker mSessionTracker;
     @Mock
     private UiEventLogger mUiEventLogger;
@@ -281,8 +279,6 @@
     @Before
     public void setup() throws RemoteException {
         MockitoAnnotations.initMocks(this);
-        when(mActivityService.getCurrentUser()).thenReturn(mCurrentUserInfo);
-        when(mActivityService.getCurrentUserId()).thenReturn(mCurrentUserId);
         when(mFaceManager.isHardwareDetected()).thenReturn(true);
         when(mAuthController.isFaceAuthEnrolled(anyInt())).thenReturn(true);
         when(mFaceManager.getSensorPropertiesInternal()).thenReturn(mFaceSensorProperties);
@@ -321,13 +317,11 @@
 
         mMockitoSession = ExtendedMockito.mockitoSession()
                 .spyStatic(SubscriptionManager.class)
-                .spyStatic(ActivityManager.class)
                 .startMocking();
         ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
                 .when(SubscriptionManager::getDefaultSubscriptionId);
         KeyguardUpdateMonitor.setCurrentUser(mCurrentUserId);
         when(mUserTracker.getUserId()).thenReturn(mCurrentUserId);
-        ExtendedMockito.doReturn(mActivityService).when(ActivityManager::getService);
 
         mContext.getOrCreateTestableResources().addOverride(
                 com.android.systemui.R.integer.config_face_auth_supported_posture,
@@ -632,20 +626,48 @@
 
     @Test
     public void testOnlyDetectFingerprint_whenFingerprintUnlockNotAllowed() {
-        // Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
-        // will trigger updateBiometricListeningState();
-        clearInvocations(mFingerprintManager);
-        mKeyguardUpdateMonitor.resetBiometricListeningState();
-
-        when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
-        mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
-        mTestableLooper.processAllMessages();
+        givenDetectFingerprintWithClearingFingerprintManagerInvocations();
 
         verifyFingerprintAuthenticateNeverCalled();
         verifyFingerprintDetectCall();
     }
 
     @Test
+    public void whenDetectFingerprint_biometricDetectCallback() {
+        ArgumentCaptor<FingerprintManager.FingerprintDetectionCallback> fpDetectCallbackCaptor =
+                ArgumentCaptor.forClass(FingerprintManager.FingerprintDetectionCallback.class);
+
+        givenDetectFingerprintWithClearingFingerprintManagerInvocations();
+        verify(mFingerprintManager).detectFingerprint(
+                any(), fpDetectCallbackCaptor.capture(), any());
+        fpDetectCallbackCaptor.getValue().onFingerprintDetected(0, 0, true);
+
+        // THEN verify keyguardUpdateMonitorCallback receives a detect callback
+        // and NO authenticate callbacks
+        verify(mTestCallback).onBiometricDetected(
+                eq(0), eq(BiometricSourceType.FINGERPRINT), eq(true));
+        verify(mTestCallback, never()).onBiometricAuthenticated(
+                anyInt(), any(), anyBoolean());
+    }
+
+    @Test
+    public void whenDetectFace_biometricDetectCallback() {
+        ArgumentCaptor<FaceManager.FaceDetectionCallback> faceDetectCallbackCaptor =
+                ArgumentCaptor.forClass(FaceManager.FaceDetectionCallback.class);
+
+        givenDetectFace();
+        verify(mFaceManager).detectFace(any(), faceDetectCallbackCaptor.capture(), any());
+        faceDetectCallbackCaptor.getValue().onFaceDetected(0, 0, false);
+
+        // THEN verify keyguardUpdateMonitorCallback receives a detect callback
+        // and NO authenticate callbacks
+        verify(mTestCallback).onBiometricDetected(
+                eq(0), eq(BiometricSourceType.FACE), eq(false));
+        verify(mTestCallback, never()).onBiometricAuthenticated(
+                anyInt(), any(), anyBoolean());
+    }
+
+    @Test
     public void testUnlockingWithFaceAllowed_strongAuthTrackerUnlockingWithBiometricAllowed() {
         // GIVEN unlocking with biometric is allowed
         strongAuthNotRequired();
@@ -673,7 +695,7 @@
         strongAuthNotRequired();
 
         // WHEN fingerprint is locked out
-        fingerprintErrorLockedOut();
+        fingerprintErrorTemporaryLockedOut();
 
         // THEN unlocking with face is not allowed
         Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
@@ -696,7 +718,7 @@
         strongAuthNotRequired();
 
         // WHEN fingerprint is locked out
-        fingerprintErrorLockedOut();
+        fingerprintErrorTemporaryLockedOut();
 
         // THEN unlocking with fingerprint is not allowed
         Assert.assertFalse(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
@@ -720,7 +742,7 @@
         Assert.assertTrue(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
 
         // WHEN fingerprint is locked out
-        fingerprintErrorLockedOut();
+        fingerprintErrorTemporaryLockedOut();
 
         // THEN user is NOT considered as "having trust" and bouncer cannot be skipped
         Assert.assertFalse(mKeyguardUpdateMonitor.getUserHasTrust(getCurrentUser()));
@@ -780,11 +802,6 @@
 
     @Test
     public void nofaceDetect_whenStrongAuthRequiredAndBypassUdfpsSupportedAndFpRunning() {
-        // GIVEN mocked keyguardUpdateMonitorCallback
-        KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback =
-                mock(KeyguardUpdateMonitorCallback.class);
-        mKeyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback);
-
         // GIVEN bypass is enabled, face detection is supported
         lockscreenBypassIsAllowed();
         supportsFaceDetection();
@@ -803,22 +820,13 @@
         verifyFaceAuthenticateNeverCalled();
 
         // THEN biometric help message sent to callback
-        verify(keyguardUpdateMonitorCallback).onBiometricHelp(
+        verify(mTestCallback).onBiometricHelp(
                 eq(BIOMETRIC_HELP_FACE_NOT_AVAILABLE), anyString(), eq(BiometricSourceType.FACE));
     }
 
     @Test
     public void faceDetect_whenStrongAuthRequiredAndBypass() {
-        // GIVEN bypass is enabled, face detection is supported and strong auth is required
-        lockscreenBypassIsAllowed();
-        supportsFaceDetection();
-        strongAuthRequiredEncrypted();
-        keyguardIsVisible();
-        // fingerprint is NOT running, UDFPS is NOT supported
-
-        // WHEN the device wakes up
-        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
-        mTestableLooper.processAllMessages();
+        givenDetectFace();
 
         // FACE detect is triggered, not authenticate
         verifyFaceDetectCall();
@@ -1066,11 +1074,6 @@
 
     @Test
     public void testBiometricsCleared_whenUserSwitches() throws Exception {
-        final IRemoteCallback reply = new IRemoteCallback.Stub() {
-            @Override
-            public void sendResult(Bundle data) {
-            } // do nothing
-        };
         final BiometricAuthenticated dummyAuthentication =
                 new BiometricAuthenticated(true /* authenticated */, true /* strong */);
         mKeyguardUpdateMonitor.mUserFaceAuthenticated.put(0 /* user */, dummyAuthentication);
@@ -1078,18 +1081,13 @@
         assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(1);
         assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(1);
 
-        mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, reply);
+        mKeyguardUpdateMonitor.handleUserSwitching(10 /* user */, new CountDownLatch(0));
         assertThat(mKeyguardUpdateMonitor.mUserFingerprintAuthenticated.size()).isEqualTo(0);
         assertThat(mKeyguardUpdateMonitor.mUserFaceAuthenticated.size()).isEqualTo(0);
     }
 
     @Test
     public void testMultiUserJankMonitor_whenUserSwitches() throws Exception {
-        final IRemoteCallback reply = new IRemoteCallback.Stub() {
-            @Override
-            public void sendResult(Bundle data) {
-            } // do nothing
-        };
         mKeyguardUpdateMonitor.handleUserSwitchComplete(10 /* user */);
         verify(mInteractionJankMonitor).end(InteractionJankMonitor.CUJ_USER_SWITCH);
         verify(mLatencyTracker).onActionEnd(LatencyTracker.ACTION_USER_SWITCH);
@@ -1152,8 +1150,7 @@
         // Fingerprint should be cancelled on lockout if going to lockout state, else
         // restarted if it's not
         assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
-                .isEqualTo(fpLocked
-                        ? BIOMETRIC_STATE_CANCELLING : BIOMETRIC_STATE_CANCELLING_RESTARTING);
+                .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
     }
 
     @Test
@@ -1612,7 +1609,7 @@
         assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
 
         // Fingerprint is locked out.
-        fingerprintErrorLockedOut();
+        fingerprintErrorTemporaryLockedOut();
 
         assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
     }
@@ -2465,7 +2462,69 @@
                 eq(false));
     }
 
+    @Test
+    public void detectFingerprint_onTemporaryLockoutReset_authenticateFingerprint() {
+        ArgumentCaptor<FingerprintManager.LockoutResetCallback> fpLockoutResetCallbackCaptor =
+                ArgumentCaptor.forClass(FingerprintManager.LockoutResetCallback.class);
+        verify(mFingerprintManager).addLockoutResetCallback(fpLockoutResetCallbackCaptor.capture());
+
+        // GIVEN device is locked out
+        fingerprintErrorTemporaryLockedOut();
+
+        // GIVEN FP detection is running
+        givenDetectFingerprintWithClearingFingerprintManagerInvocations();
+        verifyFingerprintDetectCall();
+        verifyFingerprintAuthenticateNeverCalled();
+
+        // WHEN temporary lockout resets
+        fpLockoutResetCallbackCaptor.getValue().onLockoutReset(0);
+        mTestableLooper.processAllMessages();
+
+        // THEN fingerprint detect state should cancel & then restart (for authenticate call)
+        assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
+                .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
+    }
+
+    @Test
+    public void faceAuthenticateOptions_bouncerAuthenticateReason() {
+        // GIVEN the bouncer is fully visible
+        bouncerFullyVisible();
+
+        // WHEN authenticate is called
+        ArgumentCaptor<FaceAuthenticateOptions> captor =
+                ArgumentCaptor.forClass(FaceAuthenticateOptions.class);
+        verify(mFaceManager).authenticate(any(), any(), any(), any(), captor.capture());
+
+        // THEN the authenticate reason is attributed to the bouncer
+        assertThat(captor.getValue().getAuthenticateReason())
+                .isEqualTo(AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN);
+    }
+
+    @Test
+    public void faceAuthenticateOptions_wakingUpAuthenticateReason_powerButtonWakeReason() {
+        // GIVEN keyguard is visible
+        keyguardIsVisible();
+
+        // WHEN device wakes up from the power button
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mTestableLooper.processAllMessages();
+
+        // THEN face auth is triggered
+        ArgumentCaptor<FaceAuthenticateOptions> captor =
+                ArgumentCaptor.forClass(FaceAuthenticateOptions.class);
+        verify(mFaceManager).authenticate(any(), any(), any(), any(), captor.capture());
+
+        // THEN the authenticate reason is attributed to the waking
+        assertThat(captor.getValue().getAuthenticateReason())
+                .isEqualTo(AUTHENTICATE_REASON_STARTED_WAKING_UP);
+
+        // THEN the wake reason is attributed to the power button
+        assertThat(captor.getValue().getWakeReason())
+                .isEqualTo(PowerManager.WAKE_REASON_POWER_BUTTON);
+    }
+
     private void verifyFingerprintAuthenticateNeverCalled() {
+        verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), any());
         verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
                 anyInt(), anyInt());
     }
@@ -2484,11 +2543,12 @@
     }
 
     private void verifyFaceAuthenticateNeverCalled() {
+        verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), any());
         verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
     }
 
     private void verifyFaceAuthenticateCall() {
-        verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
+        verify(mFaceManager).authenticate(any(), any(), any(), any(), any());
     }
 
     private void verifyFaceDetectNeverCalled() {
@@ -2568,7 +2628,7 @@
         mKeyguardUpdateMonitor.setSwitchingUser(true);
     }
 
-    private void fingerprintErrorLockedOut() {
+    private void fingerprintErrorTemporaryLockedOut() {
         mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback
                 .onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT, "Fingerprint locked out");
     }
@@ -2596,7 +2656,7 @@
                 any(),
                 mAuthenticationCallbackCaptor.capture(),
                 any(),
-                anyInt());
+                any());
         mAuthenticationCallbackCaptor.getValue()
                 .onAuthenticationSucceeded(
                         new FaceManager.AuthenticationResult(null, null, mCurrentUserId, false));
@@ -2707,6 +2767,30 @@
         receiver.setPendingResult(pendingResult);
     }
 
+    private void givenDetectFingerprintWithClearingFingerprintManagerInvocations() {
+        // Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
+        // will trigger updateBiometricListeningState();
+        clearInvocations(mFingerprintManager);
+        mKeyguardUpdateMonitor.resetBiometricListeningState();
+
+        when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+        mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
+        mTestableLooper.processAllMessages();
+    }
+
+    private void givenDetectFace() {
+        // GIVEN bypass is enabled, face detection is supported and strong auth is required
+        lockscreenBypassIsAllowed();
+        supportsFaceDetection();
+        strongAuthRequiredEncrypted();
+        keyguardIsVisible();
+        // fingerprint is NOT running, UDFPS is NOT supported
+
+        // WHEN the device wakes up
+        mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
+        mTestableLooper.processAllMessages();
+    }
+
     private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
         int subscription = simInited
                 ? 1/* mock subid=1 */ : SubscriptionManager.PLACEHOLDER_SUBSCRIPTION_ID_BASE;
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 6333a68..3ec49b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
@@ -354,7 +354,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_0 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_90() =
@@ -362,7 +364,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_90 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_180() =
@@ -370,7 +374,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_180 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_180() =
@@ -379,7 +385,9 @@
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_180 },
             windowInsets = insetsForSmallNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_180() =
@@ -388,7 +396,9 @@
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_180 },
             windowInsets = insetsForLargeNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_270() =
@@ -396,7 +406,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_270 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_0() =
@@ -404,7 +416,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_0 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -412,7 +426,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_90 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -421,7 +437,9 @@
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_90 },
             windowInsets = insetsForSmallNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
@@ -430,7 +448,9 @@
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_90 },
             windowInsets = insetsForLargeNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_180() =
@@ -438,7 +458,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_180 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_270() =
@@ -446,7 +468,9 @@
             deviceConfig = DeviceConfig.X_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_270 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_0() =
@@ -454,7 +478,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_0 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_90() =
@@ -462,7 +488,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_90 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_180() =
@@ -480,7 +508,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_270 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_270() =
@@ -489,7 +519,9 @@
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_270 },
             windowInsets = insetsForSmallNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_270() =
@@ -498,7 +530,9 @@
             isReverseDefaultRotation = false,
             { rotation = Surface.ROTATION_270 },
             windowInsets = insetsForLargeNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_0() =
@@ -506,7 +540,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_0 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_90() =
@@ -524,7 +560,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_180 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_InReverseDefaultRotation_180() =
@@ -533,7 +571,9 @@
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_180 },
             windowInsets = insetsForSmallNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
@@ -542,7 +582,9 @@
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_180 },
             windowInsets = insetsForLargeNavbar()
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
+        }
 
     @Test
     fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_270() =
@@ -550,7 +592,9 @@
             deviceConfig = DeviceConfig.Y_ALIGNED,
             isReverseDefaultRotation = true,
             { rotation = Surface.ROTATION_270 }
-        ) { verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true) }
+        ) {
+            verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
+        }
 
     @Test
     fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_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 e35b2a3..28e80057 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
@@ -39,11 +39,9 @@
 import com.android.systemui.settings.UserFileManager
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
-import java.io.File
-import java.util.Optional
-import java.util.function.Consumer
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
@@ -58,7 +56,9 @@
 import org.mockito.Captor
 import org.mockito.Mock
 import org.mockito.Mockito
+import org.mockito.Mockito.`when`
 import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.inOrder
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
@@ -66,9 +66,10 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyNoMoreInteractions
-import org.mockito.Mockito.`when`
-import org.mockito.Mockito.clearInvocations
 import org.mockito.MockitoAnnotations
+import java.io.File
+import java.util.*
+import java.util.function.Consumer
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -146,6 +147,7 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
+        whenever(authorizedPanelsRepository.getAuthorizedPanels()).thenReturn(setOf())
         `when`(userTracker.userHandle).thenReturn(UserHandle.of(user))
 
         delayableExecutor = FakeExecutor(FakeSystemClock())
@@ -945,6 +947,28 @@
         controller.bindComponentForPanel(TEST_COMPONENT)
         verify(bindingController).bindServiceForPanel(TEST_COMPONENT)
     }
+
+    @Test
+    fun testRemoveFavoriteRemovesFavorite() {
+        val componentName = ComponentName(context, "test.Cls")
+        controller.addFavorite(
+                componentName,
+                "test structure",
+                ControlInfo(
+                        controlId = "testId",
+                        controlTitle = "Test Control",
+                        controlSubtitle = "test control subtitle",
+                        deviceType = DeviceTypes.TYPE_LIGHT,
+                ),
+        )
+
+        controller.removeFavorites(componentName)
+        delayableExecutor.runAllReady()
+
+        verify(authorizedPanelsRepository)
+                .removeAuthorizedPanels(eq(setOf(componentName.packageName)))
+        assertThat(controller.getFavorites()).isEmpty()
+    }
 }
 
 private class DidRunRunnable() : Runnable {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
index b91a3fd..7ac1953 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/panels/AuthorizedPanelsRepositoryImplTest.kt
@@ -115,6 +115,18 @@
         assertThat(sharedPrefs.getStringSet(KEY, null)).containsExactly(TEST_PACKAGE)
     }
 
+    @Test
+    fun testRemoveAuthorizedPackageRemovesIt() {
+        val sharedPrefs = FakeSharedPreferences()
+        val fileManager = FakeUserFileManager(mapOf(0 to sharedPrefs))
+        val repository = createRepository(fileManager)
+        repository.addAuthorizedPanels(setOf(TEST_PACKAGE))
+
+        repository.removeAuthorizedPanels(setOf(TEST_PACKAGE))
+
+        assertThat(sharedPrefs.getStringSet(KEY, null)).isEmpty()
+    }
+
     private fun createRepository(userFileManager: UserFileManager): AuthorizedPanelsRepositoryImpl {
         return AuthorizedPanelsRepositoryImpl(mContext, userFileManager, userTracker)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
index 0c9986d..5a613aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/settings/ControlsSettingsDialogManagerImplTest.kt
@@ -104,7 +104,9 @@
                 controlsSettingsRepository,
                 userTracker,
                 activityStarter
-            ) { context, _ -> TestableAlertDialog(context).also { dialog = it } }
+            ) { context, _ ->
+                TestableAlertDialog(context).also { dialog = it }
+            }
     }
 
     @After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt
new file mode 100644
index 0000000..1e8cd41
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsDialogsFactoryTest.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.ui
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.FakeSystemUIDialogController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class ControlsDialogsFactoryTest : SysuiTestCase() {
+
+    private companion object {
+        const val APP_NAME = "Test App"
+    }
+
+    private val fakeDialogController = FakeSystemUIDialogController()
+
+    private lateinit var underTest: ControlsDialogsFactory
+
+    @Before
+    fun setup() {
+        underTest = ControlsDialogsFactory { fakeDialogController.dialog }
+    }
+
+    @Test
+    fun testCreatesRemoveAppDialog() {
+        val dialog = underTest.createRemoveAppDialog(context, APP_NAME) {}
+
+        verify(dialog)
+            .setTitle(
+                eq(context.getString(R.string.controls_panel_remove_app_authorization, APP_NAME))
+            )
+        verify(dialog).setCanceledOnTouchOutside(eq(true))
+    }
+
+    @Test
+    fun testPositiveClickRemoveAppDialogWorks() {
+        var dialogResult: Boolean? = null
+        underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+        fakeDialogController.clickPositive()
+
+        assertThat(dialogResult).isTrue()
+    }
+
+    @Test
+    fun testNeutralClickRemoveAppDialogWorks() {
+        var dialogResult: Boolean? = null
+        underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+        fakeDialogController.clickNeutral()
+
+        assertThat(dialogResult).isFalse()
+    }
+
+    @Test
+    fun testCancelRemoveAppDialogWorks() {
+        var dialogResult: Boolean? = null
+        underTest.createRemoveAppDialog(context, APP_NAME) { dialogResult = it }
+
+        fakeDialogController.cancel()
+
+        assertThat(dialogResult).isFalse()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
index aa90e2a..23faa99 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlsUiControllerImplTest.kt
@@ -52,6 +52,7 @@
 import com.android.systemui.statusbar.policy.DeviceControlsControllerImpl
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.FakeSharedPreferences
+import com.android.systemui.util.FakeSystemUIDialogController
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.argumentCaptor
@@ -63,21 +64,20 @@
 import com.android.wm.shell.TaskView
 import com.android.wm.shell.TaskViewFactory
 import com.google.common.truth.Truth.assertThat
-import dagger.Lazy
-import java.util.Optional
-import java.util.function.Consumer
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
+import org.mockito.Mockito.`when`
 import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.anyString
 import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.never
 import org.mockito.Mockito.spy
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
 import org.mockito.MockitoAnnotations
+import java.util.Optional
+import java.util.function.Consumer
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -98,13 +98,15 @@
     @Mock lateinit var authorizedPanelsRepository: AuthorizedPanelsRepository
     @Mock lateinit var featureFlags: FeatureFlags
     @Mock lateinit var packageManager: PackageManager
-    val sharedPreferences = FakeSharedPreferences()
-    lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
 
-    var uiExecutor = FakeExecutor(FakeSystemClock())
-    var bgExecutor = FakeExecutor(FakeSystemClock())
-    lateinit var underTest: ControlsUiControllerImpl
-    lateinit var parent: FrameLayout
+    private val sharedPreferences = FakeSharedPreferences()
+    private val fakeDialogController = FakeSystemUIDialogController()
+    private val uiExecutor = FakeExecutor(FakeSystemClock())
+    private val bgExecutor = FakeExecutor(FakeSystemClock())
+
+    private lateinit var controlsSettingsRepository: FakeControlsSettingsRepository
+    private lateinit var parent: FrameLayout
+    private lateinit var underTest: ControlsUiControllerImpl
 
     @Before
     fun setup() {
@@ -125,12 +127,12 @@
 
         underTest =
             ControlsUiControllerImpl(
-                Lazy { controlsController },
+                { controlsController },
                 context,
                 packageManager,
                 uiExecutor,
                 bgExecutor,
-                Lazy { controlsListingController },
+                { controlsListingController },
                 controlActionCoordinator,
                 activityStarter,
                 iconCache,
@@ -142,7 +144,8 @@
                 controlsSettingsRepository,
                 authorizedPanelsRepository,
                 featureFlags,
-                dumpManager
+                ControlsDialogsFactory { fakeDialogController.dialog },
+                dumpManager,
             )
         `when`(
                 userFileManager.getSharedPreferences(
@@ -410,8 +413,45 @@
         verify(controlsListingController, never()).removeCallback(any())
     }
 
+    @Test
+    fun testRemovingAppsRemovesFavorite() {
+        val componentName = ComponentName(context, "cls")
+        whenever(controlsController.removeFavorites(eq(componentName))).thenReturn(true)
+        val panel = SelectedItem.PanelItem("App name", componentName)
+        sharedPreferences
+            .edit()
+            .putString("controls_component", panel.componentName.flattenToString())
+            .putString("controls_structure", panel.appName.toString())
+            .putBoolean("controls_is_panel", true)
+            .commit()
+        underTest.show(parent, {}, context)
+        underTest.startRemovingApp(componentName, "Test App")
+
+        fakeDialogController.clickPositive()
+
+        verify(controlsController).removeFavorites(eq(componentName))
+        assertThat(underTest.getPreferredSelectedItem(emptyList()))
+            .isEqualTo(SelectedItem.EMPTY_SELECTION)
+        with(sharedPreferences) {
+            assertThat(contains("controls_component")).isFalse()
+            assertThat(contains("controls_structure")).isFalse()
+            assertThat(contains("controls_is_panel")).isFalse()
+        }
+    }
+
+    @Test
+    fun testHideCancelsTheRemoveAppDialog() {
+        val componentName = ComponentName(context, "cls")
+        underTest.show(parent, {}, context)
+        underTest.startRemovingApp(componentName, "Test App")
+
+        underTest.hide(parent)
+
+        verify(fakeDialogController.dialog).cancel()
+    }
+
     private fun setUpPanel(panel: SelectedItem.PanelItem): ControlsServiceInfo {
-        val activity = ComponentName("pkg", "activity")
+        val activity = ComponentName(context, "activity")
         sharedPreferences
             .edit()
             .putString("controls_component", panel.componentName.flattenToString())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
index dbaf94f..483ab3b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/OverflowMenuAdapterTest.kt
@@ -37,7 +37,9 @@
                 context,
                 layoutId = 0,
                 labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
-            ) { true }
+            ) {
+                true
+            }
 
         ids.forEachIndexed { index, id -> assertThat(adapter.getItemId(index)).isEqualTo(id) }
     }
@@ -51,7 +53,9 @@
                 context,
                 layoutId = 0,
                 labels.zip(ids).map { OverflowMenuAdapter.MenuItem(it.first, it.second) }
-            ) { position -> position == 0 }
+            ) { position ->
+                position == 0
+            }
 
         assertThat(adapter.isEnabled(0)).isTrue()
         assertThat(adapter.isEnabled(1)).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt b/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
new file mode 100644
index 0000000..8203291
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FACE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.settings.UserTracker
+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.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class DevicePolicyManagerExtTest : SysuiTestCase() {
+
+    @Mock lateinit var devicePolicyManager: DevicePolicyManager
+    @Mock private lateinit var userTracker: UserTracker
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        whenever(userTracker.userId).thenReturn(CURRENT_USER_ID)
+    }
+
+    // region areKeyguardShortcutsDisabled
+    @Test
+    fun areKeyguardShortcutsDisabled_noDisabledKeyguardFeature_shouldReturnFalse() {
+        whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+            .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE)
+
+        assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+            .isFalse()
+    }
+
+    @Test
+    fun areKeyguardShortcutsDisabled_otherDisabledKeyguardFeatures_shouldReturnFalse() {
+        whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+            .thenReturn(KEYGUARD_DISABLE_SECURE_CAMERA or KEYGUARD_DISABLE_FACE)
+
+        assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+            .isFalse()
+    }
+
+    @Test
+    fun areKeyguardShortcutsDisabled_disabledShortcutsKeyguardFeature_shouldReturnTrue() {
+        whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+            .thenReturn(KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+        assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+            .isTrue()
+    }
+
+    @Test
+    fun areKeyguardShortcutsDisabled_disabledAllKeyguardFeatures_shouldReturnTrue() {
+        whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+            .thenReturn(KEYGUARD_DISABLE_FEATURES_ALL)
+
+        assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+            .isTrue()
+    }
+    // endregion
+
+    private companion object {
+        const val CURRENT_USER_ID = 123
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index 9e70c27..aa17d49 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -73,6 +73,7 @@
     private static final ComponentName LOW_LIGHT_COMPONENT = new ComponentName("package",
             "lowlight");
     private static final String DREAM_COMPONENT = "package/dream";
+    private static final String WINDOW_NAME = "test";
     private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
     private final FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
 
@@ -190,7 +191,8 @@
                 mUiEventLogger,
                 mTouchInsetManager,
                 LOW_LIGHT_COMPONENT,
-                mDreamOverlayCallbackController);
+                mDreamOverlayCallbackController,
+                WINDOW_NAME);
     }
 
     public IDreamOverlayClient getClient() throws RemoteException {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
index ef62abf..175da0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
@@ -33,6 +33,8 @@
 import com.android.systemui.condition.SelfExecutingMonitor;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.BcSmartspaceDataPlugin;
 import com.android.systemui.shared.condition.Condition;
 import com.android.systemui.shared.condition.Monitor;
@@ -65,6 +67,9 @@
     @Mock
     private View mBcSmartspaceView;
 
+    @Mock
+    private FeatureFlags mFeatureFlags;
+
     private Monitor mMonitor;
 
     private final Set<Condition> mPreconditions = new HashSet<>();
@@ -73,6 +78,8 @@
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mMonitor = SelfExecutingMonitor.createInstance();
+
+        when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(false);
     }
 
     /**
@@ -85,12 +92,22 @@
         verify(mDreamOverlayStateController, never()).addComplication(eq(mComplication));
     }
 
-    private SmartSpaceComplication.Registrant getRegistrant() {
-        return new SmartSpaceComplication.Registrant(
-                mDreamOverlayStateController,
-                mComplication,
-                mSmartspaceController,
-                mMonitor);
+    @Test
+    public void testRegistrantStart_featureEnabled_addOverlayStateCallback() {
+        final SmartSpaceComplication.Registrant registrant = getRegistrant();
+        registrant.start();
+
+        verify(mDreamOverlayStateController).addCallback(any());
+    }
+
+    @Test
+    public void testRegistrantStart_featureDisabled_doesNotAddOverlayStateCallback() {
+        when(mFeatureFlags.isEnabled(Flags.HIDE_SMARTSPACE_ON_DREAM_OVERLAY)).thenReturn(true);
+
+        final SmartSpaceComplication.Registrant registrant = getRegistrant();
+        registrant.start();
+
+        verify(mDreamOverlayStateController, never()).addCallback(any());
     }
 
     @Test
@@ -188,4 +205,13 @@
         when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mBcSmartspaceView);
         assertEquals(viewHolder.getView(), viewHolder.getView());
     }
+
+    private SmartSpaceComplication.Registrant getRegistrant() {
+        return new SmartSpaceComplication.Registrant(
+                mDreamOverlayStateController,
+                mComplication,
+                mSmartspaceController,
+                mMonitor,
+                mFeatureFlags);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 7c20e3c..c93e677 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -29,7 +29,6 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -67,7 +66,6 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dreams.DreamOverlayStateController;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
@@ -136,7 +134,6 @@
     private @Mock SysuiColorExtractor mColorExtractor;
     private @Mock AuthController mAuthController;
     private @Mock ShadeExpansionStateManager mShadeExpansionStateManager;
-    private @Mock FeatureFlags mFeatureFlags;
     private @Mock ShadeWindowLogger mShadeWindowLogger;
     private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
     private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -545,7 +542,6 @@
                 mScreenOnCoordinator,
                 mInteractionJankMonitor,
                 mDreamOverlayStateController,
-                mFeatureFlags,
                 () -> mShadeController,
                 () -> mNotificationShadeWindowController,
                 () -> mActivityLaunchAnimator,
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
index 21ad5e2..5dc04f7 100644
--- 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
@@ -30,6 +30,7 @@
 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.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.AuthController
 import com.android.systemui.coroutines.collectLastValue
@@ -38,11 +39,14 @@
 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.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
 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.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestDispatcher
 import kotlinx.coroutines.test.TestScope
@@ -62,6 +66,7 @@
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
+@OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @RunWith(AndroidTestingRunner::class)
@@ -78,6 +83,7 @@
     private lateinit var biometricManagerCallback:
         ArgumentCaptor<IBiometricEnabledOnKeyguardCallback.Stub>
     private lateinit var userRepository: FakeUserRepository
+    private lateinit var devicePostureRepository: FakeDevicePostureRepository
 
     private lateinit var testDispatcher: TestDispatcher
     private lateinit var testScope: TestScope
@@ -90,6 +96,7 @@
         testDispatcher = StandardTestDispatcher()
         testScope = TestScope(testDispatcher)
         userRepository = FakeUserRepository()
+        devicePostureRepository = FakeDevicePostureRepository()
     }
 
     private suspend fun createBiometricSettingsRepository() {
@@ -108,6 +115,7 @@
                 looper = testableLooper!!.looper,
                 dumpManager = dumpManager,
                 biometricManager = biometricManager,
+                devicePostureRepository = devicePostureRepository,
             )
         testScope.runCurrent()
     }
@@ -299,6 +307,50 @@
             verify(biometricManager, times(1)).registerEnabledOnKeyguardCallback(any())
         }
 
+    @Test
+    fun faceAuthIsAlwaysSupportedIfSpecificPostureIsNotConfigured() =
+        testScope.runTest {
+            overrideResource(
+                R.integer.config_face_auth_supported_posture,
+                DevicePostureController.DEVICE_POSTURE_UNKNOWN
+            )
+
+            createBiometricSettingsRepository()
+
+            assertThat(collectLastValue(underTest.isFaceAuthSupportedInCurrentPosture)()).isTrue()
+        }
+
+    @Test
+    fun faceAuthIsSupportedOnlyWhenDevicePostureMatchesConfigValue() =
+        testScope.runTest {
+            overrideResource(
+                R.integer.config_face_auth_supported_posture,
+                DevicePostureController.DEVICE_POSTURE_FLIPPED
+            )
+
+            createBiometricSettingsRepository()
+
+            val isFaceAuthSupported =
+                collectLastValue(underTest.isFaceAuthSupportedInCurrentPosture)
+
+            assertThat(isFaceAuthSupported()).isFalse()
+
+            devicePostureRepository.setCurrentPosture(DevicePosture.CLOSED)
+            assertThat(isFaceAuthSupported()).isFalse()
+
+            devicePostureRepository.setCurrentPosture(DevicePosture.HALF_OPENED)
+            assertThat(isFaceAuthSupported()).isFalse()
+
+            devicePostureRepository.setCurrentPosture(DevicePosture.OPENED)
+            assertThat(isFaceAuthSupported()).isFalse()
+
+            devicePostureRepository.setCurrentPosture(DevicePosture.UNKNOWN)
+            assertThat(isFaceAuthSupported()).isFalse()
+
+            devicePostureRepository.setCurrentPosture(DevicePosture.FLIPPED)
+            assertThat(isFaceAuthSupported()).isTrue()
+        }
+
     private fun enrollmentChange(biometricType: BiometricType, userId: Int, enabled: Boolean) {
         authControllerCallback.value.onEnrollmentsChanged(biometricType, userId, enabled)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
new file mode 100644
index 0000000..bd6b7a8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DevicePostureRepositoryTest.kt
@@ -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.systemui.keyguard.data.repository
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import com.android.systemui.statusbar.policy.DevicePostureController
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+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.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class DevicePostureRepositoryTest : SysuiTestCase() {
+    private lateinit var underTest: DevicePostureRepository
+    private lateinit var testScope: TestScope
+    @Mock private lateinit var devicePostureController: DevicePostureController
+    @Captor private lateinit var callback: ArgumentCaptor<DevicePostureController.Callback>
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        testScope = TestScope()
+        underTest = DevicePostureRepositoryImpl(postureController = devicePostureController)
+    }
+
+    @Test
+    fun postureChangesArePropagated() =
+        testScope.runTest {
+            whenever(devicePostureController.devicePosture)
+                .thenReturn(DevicePostureController.DEVICE_POSTURE_FLIPPED)
+            val currentPosture = collectLastValue(underTest.currentDevicePosture)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.FLIPPED)
+
+            verify(devicePostureController).addCallback(callback.capture())
+
+            callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_UNKNOWN)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.UNKNOWN)
+
+            callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_CLOSED)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.CLOSED)
+
+            callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_HALF_OPENED)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.HALF_OPENED)
+
+            callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_OPENED)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.OPENED)
+
+            callback.value.onPostureChanged(DevicePostureController.DEVICE_POSTURE_FLIPPED)
+            assertThat(currentPosture()).isEqualTo(DevicePosture.FLIPPED)
+        }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 0469e77..0e6f8d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -219,6 +219,29 @@
         }
 
     @Test
+    fun isKeyguardUnlocked() =
+        runTest(UnconfinedTestDispatcher()) {
+            whenever(keyguardStateController.isUnlocked).thenReturn(false)
+            var latest: Boolean? = null
+            val job = underTest.isKeyguardUnlocked.onEach { latest = it }.launchIn(this)
+
+            assertThat(latest).isFalse()
+
+            val captor = argumentCaptor<KeyguardStateController.Callback>()
+            verify(keyguardStateController).addCallback(captor.capture())
+
+            whenever(keyguardStateController.isUnlocked).thenReturn(true)
+            captor.value.onUnlockedChanged()
+            assertThat(latest).isTrue()
+
+            whenever(keyguardStateController.isUnlocked).thenReturn(false)
+            captor.value.onUnlockedChanged()
+            assertThat(latest).isFalse()
+
+            job.cancel()
+        }
+
+    @Test
     fun isDozing() =
         runTest(UnconfinedTestDispatcher()) {
             var latest: Boolean? = null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
index d2db910..f9493d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt
@@ -62,7 +62,9 @@
             fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK)
 
             runCurrent()
-            values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+            values.assertEffectsMatchPredicates(
+                { it == DEFAULT_REVEAL_EFFECT },
+            )
 
             // We got a source but still have no sensor locations, so should be sticking with
             // the default effect.
@@ -71,14 +73,18 @@
             )
 
             runCurrent()
-            values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+            values.assertEffectsMatchPredicates(
+                { it == DEFAULT_REVEAL_EFFECT },
+            )
 
             // We got a location for the face sensor, but we unlocked with fingerprint.
             val faceLocation = Point(250, 0)
             fakeKeyguardRepository.setFaceSensorLocation(faceLocation)
 
             runCurrent()
-            values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },)
+            values.assertEffectsMatchPredicates(
+                { it == DEFAULT_REVEAL_EFFECT },
+            )
 
             // Now we have fingerprint sensor locations, and wake and unlock via fingerprint.
             val fingerprintLocation = Point(500, 500)
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 ae7a928..fe9098f 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
@@ -19,6 +19,8 @@
 import android.animation.ValueAnimator
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.flags.FakeFeatureFlags
@@ -40,6 +42,7 @@
 import com.android.systemui.shade.data.repository.FakeShadeRepository
 import com.android.systemui.shade.data.repository.ShadeRepository
 import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.mockito.withArgCaptor
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.cancelChildren
@@ -51,6 +54,8 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
 import org.mockito.Mockito.reset
 import org.mockito.Mockito.verify
@@ -77,6 +82,7 @@
     // Used to verify transition requests for test output
     @Mock private lateinit var mockTransitionRepository: KeyguardTransitionRepository
     @Mock private lateinit var commandQueue: CommandQueue
+    @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
 
     private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
     private lateinit var fromDreamingTransitionInteractor: FromDreamingTransitionInteractor
@@ -102,6 +108,8 @@
         transitionRepository = KeyguardTransitionRepositoryImpl()
         runner = KeyguardTransitionRunner(transitionRepository)
 
+        whenever(keyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(PIN)
+
         val featureFlags = FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, true) }
         fromLockscreenTransitionInteractor =
             FromLockscreenTransitionInteractor(
@@ -173,16 +181,17 @@
                 keyguardInteractor = createKeyguardInteractor(featureFlags),
                 keyguardTransitionRepository = mockTransitionRepository,
                 keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
+                keyguardSecurityModel = keyguardSecurityModel,
             )
         fromPrimaryBouncerTransitionInteractor.start()
     }
 
     @Test
-    fun `DREAMING to LOCKSCREEN - dreaming state changes first`() =
+    fun `DREAMING to LOCKSCREEN`() =
         testScope.runTest {
-            // GIVEN a device is dreaming and occluded
+            // GIVEN a device is dreaming
             keyguardRepository.setDreamingWithOverlay(true)
-            keyguardRepository.setKeyguardOccluded(true)
+            keyguardRepository.setWakefulnessModel(startingToWake())
             runCurrent()
 
             // GIVEN a prior transition has run to DREAMING
@@ -215,56 +224,7 @@
 
             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> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to BOUNCER should occur
             assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
@@ -304,7 +264,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to PRIMARY_BOUNCER should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -345,7 +305,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -386,7 +346,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
@@ -427,7 +387,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -468,7 +428,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
@@ -505,7 +465,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
@@ -542,7 +502,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
@@ -583,7 +543,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -624,7 +584,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -661,7 +621,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -677,6 +637,7 @@
         testScope.runTest {
             // GIVEN a device that is not dreaming or dozing
             keyguardRepository.setDreamingWithOverlay(false)
+            keyguardRepository.setWakefulnessModel(startingToWake())
             keyguardRepository.setDozeTransitionModel(
                 DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
             )
@@ -704,7 +665,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DREAMING should occur
             assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
@@ -741,7 +702,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to PRIMARY_BOUNCER should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -784,7 +745,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -828,7 +789,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -870,7 +831,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to LOCKSCREEN should occur
             assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
@@ -912,7 +873,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to AOD should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -954,7 +915,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to DOZING should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
@@ -995,7 +956,7 @@
 
             val info =
                 withArgCaptor<TransitionInfo> {
-                    verify(mockTransitionRepository).startTransition(capture())
+                    verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
                 }
             // THEN a transition to LOCKSCREEN should occur
             assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
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 8bd8be5..c727b3a 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
@@ -308,7 +308,7 @@
                     TestConfig(
                         isVisible = true,
                         isClickable = false,
-                        isActivated = true,
+                        isActivated = false,
                         icon = icon,
                         canShowWhileLocked = false,
                         intent = Intent("action"),
@@ -363,7 +363,7 @@
                     TestConfig(
                         isVisible = true,
                         isClickable = false,
-                        isActivated = true,
+                        isActivated = false,
                         icon = icon,
                         canShowWhileLocked = false,
                         intent = Intent("action"),
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 8c54da1..ab0669a 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
@@ -139,6 +139,7 @@
     @Mock private lateinit var logger: MediaUiEventLogger
     lateinit var mediaDataManager: MediaDataManager
     lateinit var mediaNotification: StatusBarNotification
+    lateinit var remoteCastNotification: StatusBarNotification
     @Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
     private val clock = FakeSystemClock()
     @Mock private lateinit var tunerService: TunerService
@@ -207,6 +208,20 @@
                 }
                 build()
             }
+        remoteCastNotification =
+            SbnBuilder().run {
+                setPkg(SYSTEM_PACKAGE_NAME)
+                modifyNotification(context).also {
+                    it.setSmallIcon(android.R.drawable.ic_media_pause)
+                    it.setStyle(
+                        MediaStyle().apply {
+                            setMediaSession(session.sessionToken)
+                            setRemotePlaybackInfo("Remote device", 0, null)
+                        }
+                    )
+                }
+                build()
+            }
         metadataBuilder =
             MediaMetadata.Builder().apply {
                 putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
@@ -247,6 +262,7 @@
         whenever(mediaFlags.isExplicitIndicatorEnabled()).thenReturn(true)
         whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(false)
         whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)
         whenever(logger.getNewInstanceId()).thenReturn(instanceIdSequence.newInstanceId())
         whenever(keyguardUpdateMonitor.isUserInLockdown(any())).thenReturn(false)
     }
@@ -400,33 +416,8 @@
 
     @Test
     fun testOnNotificationAdded_isRcn_markedRemote() {
-        val rcn =
-            SbnBuilder().run {
-                setPkg(SYSTEM_PACKAGE_NAME)
-                modifyNotification(context).also {
-                    it.setSmallIcon(android.R.drawable.ic_media_pause)
-                    it.setStyle(
-                        MediaStyle().apply {
-                            setMediaSession(session.sessionToken)
-                            setRemotePlaybackInfo("Remote device", 0, null)
-                        }
-                    )
-                }
-                build()
-            }
+        addNotificationAndLoad(remoteCastNotification)
 
-        mediaDataManager.onNotificationAdded(KEY, rcn)
-        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
-        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
-        verify(listener)
-            .onMediaDataLoaded(
-                eq(KEY),
-                eq(null),
-                capture(mediaDataCaptor),
-                eq(true),
-                eq(0),
-                eq(false)
-            )
         assertThat(mediaDataCaptor.value!!.playbackLocation)
             .isEqualTo(MediaData.PLAYBACK_CAST_REMOTE)
         verify(logger)
@@ -710,6 +701,56 @@
     }
 
     @Test
+    fun testOnNotificationRemoved_withResumption_isRemoteAndRemoteAllowed() {
+        // With the flag enabled to allow remote media to resume
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+        // GIVEN that the manager has a notification with a resume action, but is not local
+        whenever(controller.metadata).thenReturn(metadataBuilder.build())
+        whenever(playbackInfo.playbackType)
+            .thenReturn(MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE)
+        addNotificationAndLoad()
+        val data = mediaDataCaptor.value
+        val dataRemoteWithResume =
+            data.copy(resumeAction = Runnable {}, playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+        mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
+
+        // WHEN the notification is removed
+        mediaDataManager.onNotificationRemoved(KEY)
+
+        // THEN the media data is converted to a resume state
+        verify(listener)
+            .onMediaDataLoaded(
+                eq(PACKAGE_NAME),
+                eq(KEY),
+                capture(mediaDataCaptor),
+                eq(true),
+                eq(0),
+                eq(false)
+            )
+        assertThat(mediaDataCaptor.value.resumption).isTrue()
+    }
+
+    @Test
+    fun testOnNotificationRemoved_withResumption_isRcnAndRemoteAllowed() {
+        // With the flag enabled to allow remote media to resume
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+        // GIVEN that the manager has a remote cast notification
+        addNotificationAndLoad(remoteCastNotification)
+        val data = mediaDataCaptor.value
+        assertThat(data.playbackLocation).isEqualTo(MediaData.PLAYBACK_CAST_REMOTE)
+        val dataRemoteWithResume = data.copy(resumeAction = Runnable {})
+        mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
+
+        // WHEN the RCN is removed
+        mediaDataManager.onNotificationRemoved(KEY)
+
+        // THEN the media data is removed
+        verify(listener).onMediaDataRemoved(eq(KEY))
+    }
+
+    @Test
     fun testOnNotificationRemoved_withResumption_tooManyPlayers() {
         // Given the maximum number of resume controls already
         val desc =
@@ -1654,22 +1695,7 @@
             )
 
         // update to remote cast
-        val rcn =
-            SbnBuilder().run {
-                setPkg(SYSTEM_PACKAGE_NAME) // System package
-                modifyNotification(context).also {
-                    it.setSmallIcon(android.R.drawable.ic_media_pause)
-                    it.setStyle(
-                        MediaStyle().apply {
-                            setMediaSession(session.sessionToken)
-                            setRemotePlaybackInfo("Remote device", 0, null)
-                        }
-                    )
-                }
-                build()
-            }
-
-        mediaDataManager.onNotificationAdded(KEY, rcn)
+        mediaDataManager.onNotificationAdded(KEY, remoteCastNotification)
         assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
         assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
         verify(logger)
@@ -2038,9 +2064,14 @@
         verify(listener).onMediaDataRemoved(eq(KEY))
     }
 
-    /** Helper function to add a media notification and capture the resulting MediaData */
+    /** Helper function to add a basic media notification and capture the resulting MediaData */
     private fun addNotificationAndLoad() {
-        mediaDataManager.onNotificationAdded(KEY, mediaNotification)
+        addNotificationAndLoad(mediaNotification)
+    }
+
+    /** Helper function to add the given notification and capture the resulting MediaData */
+    private fun addNotificationAndLoad(sbn: StatusBarNotification) {
+        mediaDataManager.onNotificationAdded(KEY, sbn)
         assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
         assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
         verify(listener)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
index 136ace1..4dfa626 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/resume/MediaResumeListenerTest.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.media.controls.models.player.MediaDeviceData
 import com.android.systemui.media.controls.pipeline.MediaDataManager
 import com.android.systemui.media.controls.pipeline.RESUME_MEDIA_TIMEOUT
+import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.tuner.TunerService
 import com.android.systemui.util.concurrency.FakeExecutor
@@ -92,6 +93,7 @@
     @Mock private lateinit var mockContext: Context
     @Mock private lateinit var pendingIntent: PendingIntent
     @Mock private lateinit var dumpManager: DumpManager
+    @Mock private lateinit var mediaFlags: MediaFlags
 
     @Captor lateinit var callbackCaptor: ArgumentCaptor<ResumeMediaBrowser.Callback>
     @Captor lateinit var actionCaptor: ArgumentCaptor<Runnable>
@@ -134,6 +136,7 @@
         whenever(mockContext.packageManager).thenReturn(context.packageManager)
         whenever(mockContext.contentResolver).thenReturn(context.contentResolver)
         whenever(mockContext.userId).thenReturn(context.userId)
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(false)
 
         executor = FakeExecutor(clock)
         resumeListener =
@@ -146,7 +149,8 @@
                 tunerService,
                 resumeBrowserFactory,
                 dumpManager,
-                clock
+                clock,
+                mediaFlags,
             )
         resumeListener.setManager(mediaDataManager)
         mediaDataManager.addListener(resumeListener)
@@ -188,7 +192,8 @@
                 tunerService,
                 resumeBrowserFactory,
                 dumpManager,
-                clock
+                clock,
+                mediaFlags,
             )
         listener.setManager(mediaDataManager)
         verify(broadcastDispatcher, never())
@@ -244,6 +249,32 @@
     }
 
     @Test
+    fun testOnLoad_localCast_remoteResumeAllowed_doesCheck() {
+        // If local cast media is allowed to resume
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+        // When media data is loaded that has not been checked yet, and is a local cast
+        val dataCast = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+        resumeListener.onMediaDataLoaded(KEY, null, dataCast)
+
+        // Then we report back to the manager
+        verify(mediaDataManager).setResumeAction(KEY, null)
+    }
+
+    @Test
+    fun testOnLoad_remoteCast_remoteResumeAllowed_doesCheck() {
+        // If local cast media is allowed to resume
+        whenever(mediaFlags.isRemoteResumeAllowed()).thenReturn(true)
+
+        // When media data is loaded that has not been checked yet, and is a remote cast
+        val dataRcn = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_REMOTE)
+        resumeListener.onMediaDataLoaded(KEY, null, dataRcn)
+
+        // Then we do not take action
+        verify(mediaDataManager, never()).setResumeAction(any(), any())
+    }
+
+    @Test
     fun testOnLoad_checksForResume_hasService() {
         setUpMbsWithValidResolveInfo()
 
@@ -389,7 +420,8 @@
                 tunerService,
                 resumeBrowserFactory,
                 dumpManager,
-                clock
+                clock,
+                mediaFlags,
             )
         resumeListener.setManager(mediaDataManager)
         mediaDataManager.addListener(resumeListener)
@@ -421,7 +453,8 @@
                 tunerService,
                 resumeBrowserFactory,
                 dumpManager,
-                clock
+                clock,
+                mediaFlags,
             )
         resumeListener.setManager(mediaDataManager)
         mediaDataManager.addListener(resumeListener)
@@ -463,7 +496,8 @@
                 tunerService,
                 resumeBrowserFactory,
                 dumpManager,
-                clock
+                clock,
+                mediaFlags,
             )
         resumeListener.setManager(mediaDataManager)
         mediaDataManager.addListener(resumeListener)
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 4fc9ca7..85e8d07 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
@@ -70,8 +70,7 @@
                 context,
                 appPackageName = null,
                 isReceiver = false,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isFalse()
         assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -86,8 +85,7 @@
                 context,
                 appPackageName = null,
                 isReceiver = true,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isFalse()
         assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -119,8 +117,7 @@
                 context,
                 appPackageName = "fakePackageName",
                 isReceiver = false,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isFalse()
         assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -135,8 +132,7 @@
                 context,
                 appPackageName = "fakePackageName",
                 isReceiver = true,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isFalse()
         assertThat(iconInfo.contentDescription.loadContentDescription(context))
@@ -154,7 +150,9 @@
             context,
             appPackageName = "fakePackageName",
             isReceiver = false
-        ) { exceptionTriggered = true }
+        ) {
+            exceptionTriggered = true
+        }
 
         assertThat(exceptionTriggered).isTrue()
     }
@@ -167,7 +165,9 @@
             context,
             appPackageName = "fakePackageName",
             isReceiver = true
-        ) { exceptionTriggered = true }
+        ) {
+            exceptionTriggered = true
+        }
 
         assertThat(exceptionTriggered).isTrue()
     }
@@ -179,8 +179,7 @@
                 context,
                 PACKAGE_NAME,
                 isReceiver = false,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isTrue()
         assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
@@ -194,8 +193,7 @@
                 context,
                 PACKAGE_NAME,
                 isReceiver = true,
-            ) {
-            }
+            ) {}
 
         assertThat(iconInfo.isAppIcon).isTrue()
         assertThat(iconInfo.icon).isEqualTo(MediaTttIcon.Loaded(appIconFromPackageName))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 2212bbd..89405c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -141,8 +141,8 @@
 
     @Test
     public void testCreateNavigationBarsIncludeDefaultTrue() {
-        // Tablets may be using taskbar and the logic is different
-        mNavigationBarController.mIsTablet = false;
+        // Large screens may be using taskbar and the logic is different
+        mNavigationBarController.mIsLargeScreen = false;
         doNothing().when(mNavigationBarController).createNavigationBar(any(), any(), any());
 
         mNavigationBarController.createNavigationBars(true, null);
@@ -290,7 +290,7 @@
     @Test
     public void testConfigurationChange_taskbarNotInitialized() {
         Configuration configuration = mContext.getResources().getConfiguration();
-        when(Utilities.isTablet(any())).thenReturn(true);
+        when(Utilities.isLargeScreen(any())).thenReturn(true);
         mNavigationBarController.onConfigChanged(configuration);
         verify(mTaskbarDelegate, never()).onConfigurationChanged(configuration);
     }
@@ -298,7 +298,7 @@
     @Test
     public void testConfigurationChange_taskbarInitialized() {
         Configuration configuration = mContext.getResources().getConfiguration();
-        when(Utilities.isTablet(any())).thenReturn(true);
+        when(Utilities.isLargeScreen(any())).thenReturn(true);
         when(mTaskbarDelegate.isInitialized()).thenReturn(true);
         mNavigationBarController.onConfigChanged(configuration);
         verify(mTaskbarDelegate, times(1)).onConfigurationChanged(configuration);
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 39c4e06..376b7cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -16,40 +16,36 @@
 package com.android.systemui.notetask
 
 import android.app.KeyguardManager
+import android.app.admin.DevicePolicyManager
 import android.content.ComponentName
 import android.content.Context
 import android.content.Intent
 import android.content.pm.PackageManager
 import android.os.UserManager
-import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
-import com.android.internal.logging.UiEventLogger
 import com.android.systemui.SysuiTestCase
-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.settings.UserTracker
+import com.android.systemui.util.mockito.any
 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.Bubble
 import com.android.wm.shell.bubbles.Bubbles
 import com.google.common.truth.Truth.assertThat
 import java.util.Optional
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyZeroInteractions
 import org.mockito.MockitoAnnotations
 
-/**
- * Tests for [NoteTaskController].
- *
- * Build/Install/Run:
- * - atest SystemUITests:NoteTaskControllerTest
- */
+/** atest SystemUITests:NoteTaskControllerTest */
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 internal class NoteTaskControllerTest : SysuiTestCase() {
@@ -58,191 +54,301 @@
     @Mock lateinit var packageManager: PackageManager
     @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
+    @Mock lateinit var eventLogger: NoteTaskEventLogger
+    @Mock private lateinit var userTracker: UserTracker
+    @Mock private lateinit var devicePolicyManager: DevicePolicyManager
+
+    private val noteTaskInfo = NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
         whenever(context.packageManager).thenReturn(packageManager)
-        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)
+        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(noteTaskInfo)
         whenever(userManager.isUserUnlocked).thenReturn(true)
+        whenever(
+                devicePolicyManager.getKeyguardDisabledFeatures(
+                    /* admin= */ eq(null),
+                    /* userHandle= */ anyInt()
+                )
+            )
+            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE)
     }
 
-    private fun createNoteTaskController(isEnabled: Boolean = true): NoteTaskController {
-        return NoteTaskController(
+    private fun createNoteTaskController(
+        isEnabled: Boolean = true,
+        bubbles: Bubbles? = this.bubbles,
+        keyguardManager: KeyguardManager? = this.keyguardManager,
+        userManager: UserManager? = this.userManager,
+    ): NoteTaskController =
+        NoteTaskController(
             context = context,
             resolver = resolver,
-            optionalBubbles = optionalBubbles,
-            optionalKeyguardManager = optionalKeyguardManager,
-            optionalUserManager = optionalUserManager,
+            eventLogger = eventLogger,
+            optionalBubbles = Optional.ofNullable(bubbles),
+            optionalUserManager = Optional.ofNullable(userManager),
+            optionalKeyguardManager = Optional.ofNullable(keyguardManager),
             isEnabled = isEnabled,
-            uiEventLogger = uiEventLogger,
+            devicePolicyManager = devicePolicyManager,
+            userTracker = userTracker,
         )
+
+    // region onBubbleExpandChanged
+    @Test
+    fun onBubbleExpandChanged_expanding_logNoteTaskOpened() {
+        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = false)
+
+        createNoteTaskController()
+            .apply { infoReference.set(expectedInfo) }
+            .onBubbleExpandChanged(
+                isExpanding = true,
+                key = Bubble.KEY_APP_BUBBLE,
+            )
+
+        verify(eventLogger).logNoteTaskOpened(expectedInfo)
+        verifyZeroInteractions(context, bubbles, keyguardManager, userManager)
     }
 
+    @Test
+    fun onBubbleExpandChanged_collapsing_logNoteTaskClosed() {
+        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = false)
+
+        createNoteTaskController()
+            .apply { infoReference.set(expectedInfo) }
+            .onBubbleExpandChanged(
+                isExpanding = false,
+                key = Bubble.KEY_APP_BUBBLE,
+            )
+
+        verify(eventLogger).logNoteTaskClosed(expectedInfo)
+        verifyZeroInteractions(context, bubbles, keyguardManager, userManager)
+    }
+
+    @Test
+    fun onBubbleExpandChanged_expandingAndKeyguardLocked_doNothing() {
+        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = true, isInMultiWindowMode = false)
+
+        createNoteTaskController()
+            .apply { infoReference.set(expectedInfo) }
+            .onBubbleExpandChanged(
+                isExpanding = true,
+                key = Bubble.KEY_APP_BUBBLE,
+            )
+
+        verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+    }
+
+    @Test
+    fun onBubbleExpandChanged_notExpandingAndKeyguardLocked_doNothing() {
+        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = true, isInMultiWindowMode = false)
+
+        createNoteTaskController()
+            .apply { infoReference.set(expectedInfo) }
+            .onBubbleExpandChanged(
+                isExpanding = false,
+                key = Bubble.KEY_APP_BUBBLE,
+            )
+
+        verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+    }
+
+    @Test
+    fun onBubbleExpandChanged_expandingAndInMultiWindowMode_doNothing() {
+        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = true)
+
+        createNoteTaskController()
+            .apply { infoReference.set(expectedInfo) }
+            .onBubbleExpandChanged(
+                isExpanding = true,
+                key = Bubble.KEY_APP_BUBBLE,
+            )
+
+        verifyZeroInteractions(context, bubbles, keyguardManager, userManager)
+    }
+
+    @Test
+    fun onBubbleExpandChanged_notExpandingAndInMultiWindowMode_doNothing() {
+        val expectedInfo = noteTaskInfo.copy(isKeyguardLocked = false, isInMultiWindowMode = true)
+
+        createNoteTaskController()
+            .apply { infoReference.set(expectedInfo) }
+            .onBubbleExpandChanged(
+                isExpanding = false,
+                key = Bubble.KEY_APP_BUBBLE,
+            )
+
+        verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+    }
+
+    @Test
+    fun onBubbleExpandChanged_notKeyAppBubble_shouldDoNothing() {
+        createNoteTaskController()
+            .onBubbleExpandChanged(
+                isExpanding = true,
+                key = "any other key",
+            )
+
+        verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+    }
+
+    @Test
+    fun onBubbleExpandChanged_flagDisabled_shouldDoNothing() {
+        createNoteTaskController(isEnabled = false)
+            .onBubbleExpandChanged(
+                isExpanding = true,
+                key = Bubble.KEY_APP_BUBBLE,
+            )
+
+        verifyZeroInteractions(context, bubbles, keyguardManager, userManager, eventLogger)
+    }
+    // endregion
+
     // region showNoteTask
     @Test
     fun showNoteTask_keyguardIsLocked_shouldStartActivityAndLogUiEvent() {
-        whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+        val expectedInfo =
+            noteTaskInfo.copy(
+                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+                isInMultiWindowMode = false,
+                isKeyguardLocked = true,
+            )
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
+        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
 
         createNoteTaskController()
             .showNoteTask(
-                isInMultiWindowMode = false,
-                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE,
+                entryPoint = expectedInfo.entryPoint!!,
+                isInMultiWindowMode = expectedInfo.isInMultiWindowMode,
             )
 
         val intentCaptor = argumentCaptor<Intent>()
         verify(context).startActivity(capture(intentCaptor))
         intentCaptor.value.let { intent ->
-            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+            assertThat(intent.action).isEqualTo(Intent.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()
+            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
         }
+        verify(eventLogger).logNoteTaskOpened(expectedInfo)
         verifyZeroInteractions(bubbles)
-        verify(uiEventLogger)
-            .log(
-                ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE,
-                NOTES_UID,
-                NOTES_PACKAGE_NAME
-            )
     }
 
     @Test
-    fun showNoteTask_keyguardIsUnlocked_shouldStartBubblesAndLogUiEvent() {
-        whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+    fun showNoteTask_keyguardIsUnlocked_shouldStartBubblesWithoutLoggingUiEvent() {
+        val expectedInfo =
+            noteTaskInfo.copy(
+                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+                isInMultiWindowMode = false,
+                isKeyguardLocked = false,
+            )
+        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
 
         createNoteTaskController()
             .showNoteTask(
-                isInMultiWindowMode = false,
-                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
+                entryPoint = expectedInfo.entryPoint!!,
+                isInMultiWindowMode = expectedInfo.isInMultiWindowMode,
             )
 
         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.action).isEqualTo(Intent.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()
+            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_keyguardIsUnlocked_uiEventIsNull_shouldStartBubblesWithoutLoggingUiEvent() {
-        whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
-
-        createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
-
-        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)
+        verifyZeroInteractions(eventLogger)
     }
 
     @Test
     fun showNoteTask_isInMultiWindowMode_shouldStartActivityAndLogUiEvent() {
-        whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+        val expectedInfo =
+            noteTaskInfo.copy(
+                entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT,
+                isInMultiWindowMode = true,
+                isKeyguardLocked = false,
+            )
+        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
 
         createNoteTaskController()
             .showNoteTask(
-                isInMultiWindowMode = true,
-                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT,
+                entryPoint = expectedInfo.entryPoint!!,
+                isInMultiWindowMode = expectedInfo.isInMultiWindowMode,
             )
 
         val intentCaptor = argumentCaptor<Intent>()
         verify(context).startActivity(capture(intentCaptor))
         intentCaptor.value.let { intent ->
-            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+            assertThat(intent.action).isEqualTo(Intent.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()
+            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
         }
+        verify(eventLogger).logNoteTaskOpened(expectedInfo)
         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()
+        createNoteTaskController(bubbles = null)
             .showNoteTask(
+                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
                 isInMultiWindowMode = false,
-                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
             )
 
-        verifyZeroInteractions(context, bubbles, uiEventLogger)
+        verifyZeroInteractions(context, bubbles, eventLogger)
     }
 
     @Test
     fun showNoteTask_keyguardManagerIsNull_shouldDoNothing() {
-        whenever(optionalKeyguardManager.orElse(null)).thenReturn(null)
-
-        createNoteTaskController()
+        createNoteTaskController(keyguardManager = null)
             .showNoteTask(
+                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
                 isInMultiWindowMode = false,
-                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
             )
 
-        verifyZeroInteractions(context, bubbles, uiEventLogger)
+        verifyZeroInteractions(context, bubbles, eventLogger)
     }
 
     @Test
     fun showNoteTask_userManagerIsNull_shouldDoNothing() {
-        whenever(optionalUserManager.orElse(null)).thenReturn(null)
-
-        createNoteTaskController()
+        createNoteTaskController(userManager = null)
             .showNoteTask(
+                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
                 isInMultiWindowMode = false,
-                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
             )
 
-        verifyZeroInteractions(context, bubbles, uiEventLogger)
+        verifyZeroInteractions(context, bubbles, eventLogger)
     }
 
     @Test
     fun showNoteTask_intentResolverReturnsNull_shouldDoNothing() {
-        whenever(resolver.resolveInfo()).thenReturn(null)
+        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(null)
 
         createNoteTaskController()
             .showNoteTask(
+                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
                 isInMultiWindowMode = false,
-                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
             )
 
-        verifyZeroInteractions(context, bubbles, uiEventLogger)
+        verifyZeroInteractions(context, bubbles, eventLogger)
     }
 
     @Test
     fun showNoteTask_flagDisabled_shouldDoNothing() {
         createNoteTaskController(isEnabled = false)
-            .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON)
+            .showNoteTask(
+                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+                isInMultiWindowMode = false,
+            )
 
-        verifyZeroInteractions(context, bubbles, uiEventLogger)
+        verifyZeroInteractions(context, bubbles, eventLogger)
     }
 
     @Test
@@ -251,11 +357,11 @@
 
         createNoteTaskController()
             .showNoteTask(
+                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
                 isInMultiWindowMode = false,
-                uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON,
             )
 
-        verifyZeroInteractions(context, bubbles, uiEventLogger)
+        verifyZeroInteractions(context, bubbles, eventLogger)
     }
     // endregion
 
@@ -291,6 +397,102 @@
     }
     // endregion
 
+    // region keyguard policy
+    @Test
+    fun showNoteTask_keyguardLocked_keyguardDisableShortcutsAll_shouldDoNothing() {
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+        whenever(
+                devicePolicyManager.getKeyguardDisabledFeatures(
+                    /* admin= */ eq(null),
+                    /* userHandle= */ anyInt()
+                )
+            )
+            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE
+            )
+
+        verifyZeroInteractions(context, bubbles, eventLogger)
+    }
+
+    @Test
+    fun showNoteTask_keyguardLocked_keyguardDisableFeaturesAll_shouldDoNothing() {
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+        whenever(
+                devicePolicyManager.getKeyguardDisabledFeatures(
+                    /* admin= */ eq(null),
+                    /* userHandle= */ anyInt()
+                )
+            )
+            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE
+            )
+
+        verifyZeroInteractions(context, bubbles, eventLogger)
+    }
+
+    @Test
+    fun showNoteTask_keyguardUnlocked_keyguardDisableShortcutsAll_shouldStartBubble() {
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+        whenever(
+                devicePolicyManager.getKeyguardDisabledFeatures(
+                    /* admin= */ eq(null),
+                    /* userHandle= */ anyInt()
+                )
+            )
+            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE
+            )
+
+        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()
+        }
+    }
+
+    @Test
+    fun showNoteTask_keyguardUnlocked_keyguardDisableFeaturesAll_shouldStartBubble() {
+        whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+        whenever(
+                devicePolicyManager.getKeyguardDisabledFeatures(
+                    /* admin= */ eq(null),
+                    /* userHandle= */ anyInt()
+                )
+            )
+            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+
+        createNoteTaskController()
+            .showNoteTask(
+                isInMultiWindowMode = false,
+                entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE
+            )
+
+        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()
+        }
+    }
+    // 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/NoteTaskEventLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt
new file mode 100644
index 0000000..a4df346
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskEventLoggerTest.kt
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.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.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.MockitoAnnotations
+
+/** atest SystemUITests:MonitoringNoteTaskEventListenerTest */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+internal class NoteTaskEventLoggerTest : SysuiTestCase() {
+
+    @Mock lateinit var uiEventLogger: UiEventLogger
+
+    private fun createNoteTaskEventLogger(): NoteTaskEventLogger =
+        NoteTaskEventLogger(uiEventLogger)
+
+    private fun createNoteTaskInfo(): NoteTaskInfo =
+        NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+    }
+
+    // region logNoteTaskOpened
+    @Test
+    fun logNoteTaskOpened_entryPointWidgetPickerShortcut_noteOpenedViaShortcut() {
+        val info = createNoteTaskInfo().copy(entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT)
+
+        createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+        val expected = NOTE_OPENED_VIA_SHORTCUT
+        verify(uiEventLogger).log(expected, info.uid, info.packageName)
+    }
+
+    @Test
+    fun onNoteTaskBubbleExpanded_entryPointQuickAffordance_noteOpenedViaQuickAffordance() {
+        val info = createNoteTaskInfo().copy(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
+
+        createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+        val expected = NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE
+        verify(uiEventLogger).log(expected, info.uid, info.packageName)
+    }
+
+    @Test
+    fun onNoteTaskBubbleExpanded_entryPointTailButtonAndIsKeyguardUnlocked_noteOpenedViaTailButtonUnlocked() { // ktlint-disable max-line-length
+        val info =
+            createNoteTaskInfo()
+                .copy(
+                    entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+                    isKeyguardLocked = false,
+                )
+
+        createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+        val expected = NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON
+        verify(uiEventLogger).log(expected, info.uid, info.packageName)
+    }
+
+    @Test
+    fun onNoteTaskBubbleExpanded_entryPointTailButtonAndIsKeyguardLocked_noteOpenedViaTailButtonLocked() { // ktlint-disable max-line-length
+        val info =
+            createNoteTaskInfo()
+                .copy(
+                    entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+                    isKeyguardLocked = true,
+                )
+
+        createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+        val expected = NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+        verify(uiEventLogger).log(expected, info.uid, info.packageName)
+    }
+
+    @Test
+    fun onNoteTaskBubbleExpanded_noEntryPoint_noLog() {
+        val info = createNoteTaskInfo().copy(entryPoint = null)
+
+        createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+        verifyNoMoreInteractions(uiEventLogger)
+    }
+    // endregion
+
+    // region logNoteTaskClosed
+    @Test
+    fun logNoteTaskClosed_entryPointTailButton_noteClosedViaTailButtonUnlocked() {
+        val info =
+            createNoteTaskInfo()
+                .copy(
+                    entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+                    isKeyguardLocked = false,
+                )
+
+        createNoteTaskEventLogger().logNoteTaskClosed(info)
+
+        val expected = NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON
+        verify(uiEventLogger).log(expected, info.uid, info.packageName)
+    }
+
+    @Test
+    fun logNoteTaskClosed_entryPointTailButtonAndKeyguardLocked_noteClosedViaTailButtonLocked() {
+        val info =
+            createNoteTaskInfo()
+                .copy(
+                    entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
+                    isKeyguardLocked = true,
+                )
+
+        createNoteTaskEventLogger().logNoteTaskClosed(info)
+
+        val expected = NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED
+        verify(uiEventLogger).log(expected, info.uid, info.packageName)
+    }
+
+    @Test
+    fun logNoteTaskClosed_noEntryPoint_noLog() {
+        val info = createNoteTaskInfo().copy(entryPoint = null)
+
+        createNoteTaskEventLogger().logNoteTaskOpened(info)
+
+        verifyNoMoreInteractions(uiEventLogger)
+    }
+    // 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
index d6495d8..7f64f8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoResolverTest.kt
@@ -57,8 +57,9 @@
     fun resolveInfo_shouldReturnInfo() {
         val packageName = "com.android.note.app"
         val uid = 123456
-        whenever(roleManager.getRoleHoldersAsUser(NoteTaskInfoResolver.ROLE_NOTES, context.user))
-            .then { listOf(packageName) }
+        whenever(roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, context.user)).then {
+            listOf(packageName)
+        }
         whenever(
                 packageManager.getApplicationInfoAsUser(
                     eq(packageName),
@@ -78,8 +79,9 @@
     @Test
     fun resolveInfo_packageManagerThrowsException_shouldReturnInfoWithZeroUid() {
         val packageName = "com.android.note.app"
-        whenever(roleManager.getRoleHoldersAsUser(NoteTaskInfoResolver.ROLE_NOTES, context.user))
-            .then { listOf(packageName) }
+        whenever(roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, context.user)).then {
+            listOf(packageName)
+        }
         whenever(
                 packageManager.getApplicationInfoAsUser(
                     eq(packageName),
@@ -98,8 +100,9 @@
 
     @Test
     fun resolveInfo_noRoleHolderIsSet_shouldReturnNull() {
-        whenever(roleManager.getRoleHoldersAsUser(eq(NoteTaskInfoResolver.ROLE_NOTES), any()))
-            .then { listOf<String>() }
+        whenever(roleManager.getRoleHoldersAsUser(eq(RoleManager.ROLE_NOTES), any())).then {
+            emptyList<String>()
+        }
 
         val actual = underTest.resolveInfo()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
new file mode 100644
index 0000000..7e975b6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInfoTest.kt
@@ -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.notetask
+
+import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** atest SystemUITests:NoteTaskInfoTest */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+internal class NoteTaskInfoTest : SysuiTestCase() {
+
+    private fun createNoteTaskInfo(): NoteTaskInfo =
+        NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
+
+    @Test
+    fun launchMode_notInMultiWindowModeAndKeyguardUnlocked_launchModeAppBubble() {
+        val underTest =
+            createNoteTaskInfo()
+                .copy(
+                    isKeyguardLocked = false,
+                    isInMultiWindowMode = false,
+                )
+
+        assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.AppBubble)
+    }
+
+    @Test
+    fun launchMode_inMultiWindowMode_launchModeActivity() {
+        val underTest =
+            createNoteTaskInfo()
+                .copy(
+                    isKeyguardLocked = false,
+                    isInMultiWindowMode = true,
+                )
+
+        assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
+    }
+
+    @Test
+    fun launchMode_keyguardLocked_launchModeActivity() {
+        val underTest =
+            createNoteTaskInfo()
+                .copy(
+                    isKeyguardLocked = true,
+                    isInMultiWindowMode = false,
+                )
+
+        assertThat(underTest.launchMode).isEqualTo(NoteTaskLaunchMode.Activity)
+    }
+
+    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/NoteTaskInitializerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
index 53720ff..46e0278 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskInitializerTest.kt
@@ -15,15 +15,11 @@
  */
 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
 import org.junit.Before
@@ -48,27 +44,22 @@
 
     @Mock lateinit var commandQueue: CommandQueue
     @Mock lateinit var bubbles: Bubbles
-    @Mock lateinit var optionalBubbles: Optional<Bubbles>
     @Mock lateinit var noteTaskController: NoteTaskController
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-
-        whenever(optionalBubbles.isPresent).thenReturn(true)
-        whenever(optionalBubbles.orElse(null)).thenReturn(bubbles)
     }
 
     private fun createNoteTaskInitializer(
         isEnabled: Boolean = true,
-        optionalKeyguardManager: Optional<KeyguardManager> = Optional.empty(),
+        bubbles: Bubbles? = this.bubbles,
     ): NoteTaskInitializer {
         return NoteTaskInitializer(
-            optionalBubbles = optionalBubbles,
-            noteTaskController = noteTaskController,
+            controller = noteTaskController,
             commandQueue = commandQueue,
+            optionalBubbles = Optional.ofNullable(bubbles),
             isEnabled = isEnabled,
-            optionalKeyguardManager = optionalKeyguardManager,
         )
     }
 
@@ -89,9 +80,7 @@
 
     @Test
     fun initialize_bubblesNotPresent_shouldDoNothing() {
-        whenever(optionalBubbles.isPresent).thenReturn(false)
-
-        createNoteTaskInitializer().initialize()
+        createNoteTaskInitializer(bubbles = null).initialize()
 
         verify(commandQueue, never()).addCallback(any())
     }
@@ -113,37 +102,10 @@
 
     // region handleSystemKey
     @Test
-    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)
+    fun handleSystemKey_receiveValidSystemKey_shouldShowNoteTask() {
+        createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL)
 
-        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)
+        verify(noteTaskController).showNoteTask(entryPoint = NoteTaskEntryPoint.TAIL_BUTTON)
     }
 
     @Test
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 cdc683f..e57d0d9 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.notetask.NoteTaskController.ShowNoteTaskUiEvent
+import com.android.systemui.notetask.NoteTaskEntryPoint
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
@@ -95,7 +95,6 @@
 
         underTest.onTriggered(expandable = null)
 
-        verify(noteTaskController)
-            .showNoteTask(uiEvent = ShowNoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE)
+        verify(noteTaskController).showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
index 030c59f..5e0190b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.util.settings.GlobalSettings
 import com.google.common.truth.Truth.assertThat
 import dagger.Lazy
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -94,6 +95,12 @@
             mUserTracker)
     }
 
+    @After
+    fun tearDown() {
+        mTile.destroy()
+        mTestableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenDisabled_showsOffState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
index b4a66297..f1e3e8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -88,6 +89,12 @@
         testableLooper.processAllMessages()
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testAvailable() {
         assertThat(tile.isAvailable).isTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
index 95e7ad9f..a5c0004 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
@@ -37,6 +37,7 @@
 import com.android.systemui.util.settings.FakeSettings
 import com.android.systemui.util.settings.SecureSettings
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Test
@@ -103,6 +104,12 @@
         testableLooper.processAllMessages()
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testSettingWithCorrectUser() {
         assertEquals(USER, tile.mSetting.currentUser)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
index bf172f1..75fd000 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.statusbar.policy.BluetoothController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -79,6 +80,12 @@
         testableLooper.processAllMessages()
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testRestrictionChecked() {
         tile.refreshState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
index cfbb82f..4193854 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -90,6 +91,12 @@
                 keyguardStateController)
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenCameraAccessEnabled_isOnState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
index 18f891c..64fd09d5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CastTileTest.java
@@ -53,6 +53,7 @@
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -141,6 +142,12 @@
         mHotspotCallback = hotspotCallbackArgumentCaptor.getValue();
     }
 
+    @After
+    public void tearDown() {
+        mCastTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     // -------------------------------------------------
     // All these tests for enabled/disabled wifi have hotspot not enabled
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
index fdb63ca..13c30e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorCorrectionTileTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.settings.SecureSettings;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -101,6 +102,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void longClick_expectedAction() {
         final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
index 60c1a33..ff27e02 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
@@ -46,6 +46,7 @@
 import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.settings.SecureSettings;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -106,6 +107,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void longClick_expectedAction() {
         final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
index ce62f2d..b048643 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt
@@ -34,6 +34,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.statusbar.policy.DataSaverController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -84,6 +85,12 @@
             )
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenDataSaverEnabled_isOnState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index e0b3125..b51c378 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -67,6 +67,7 @@
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.verifyZeroInteractions
 import java.util.Optional
+import org.junit.After
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -129,6 +130,12 @@
         tile = createTile()
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     private fun setupControlsComponent() {
         `when`(controlsComponent.getControlsController()).thenAnswer {
             if (featureEnabled) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
index ce5edb1..6c0904e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
@@ -136,7 +136,8 @@
 
     @After
     fun tearDown() {
-        tile.handleSetListening(false)
+        tile.destroy()
+        testableLooper.processAllMessages()
     }
 
     @Test
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 71d8aa4..7d41aa6 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
@@ -54,6 +54,7 @@
 import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.settings.SecureSettings;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -112,6 +113,12 @@
         mTile.initialize();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testNotAvailable() throws RemoteException {
         // Should not be available if screensaver is disabled
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
index c7aba1a..692a644 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FlashlightTileTest.kt
@@ -18,6 +18,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.statusbar.policy.FlashlightController
 import com.google.common.truth.Truth
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -71,6 +72,12 @@
             )
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenFlashlightEnabled_isOnState() {
         Mockito.`when`(flashlightController.isAvailable).thenReturn(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
index 9d62cfd..bd99cd4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/FontScalingTileTest.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.util.mockito.nullable
 import com.android.systemui.util.settings.FakeSettings
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -89,6 +90,12 @@
         testableLooper.processAllMessages()
     }
 
+    @After
+    fun tearDown() {
+        fontScalingTile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun isAvailable_whenFlagIsFalse_returnsFalse() {
         featureFlags.set(Flags.ENABLE_FONT_SCALING_TILE, false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
index 4a2ac96..959e750 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HotspotTileTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.HotspotController;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -94,6 +95,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void handleUpdateState_wifiTetheringIsAllowed_stateIsNotUnavailable() {
         MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
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 abd9094..adfd7f7 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
@@ -43,6 +43,7 @@
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.connectivity.WifiIndicators;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -91,6 +92,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void setConnectivityStatus_defaultNetworkNotExists_updateTile() {
         mTile.mSignalCallback.setConnectivityStatus(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
index 08d10fd..33921c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.statusbar.policy.LocationController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -88,6 +89,12 @@
             keyguardStateController)
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenDisabled_isOffState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
index 1ab601c..e2f64b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
@@ -35,6 +35,7 @@
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -90,6 +91,12 @@
                 keyguardStateController)
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenMicrophoneAccessEnabled_isOnState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
index 9638a45..c7dae83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NfcTileTest.java
@@ -39,6 +39,7 @@
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.logging.QSLogger;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -97,6 +98,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mNfcTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testIsAvailable_stockWithoutNfc_returnsFalse() {
         when(mMockContext.getString(R.string.quick_settings_tiles_stock)).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
index 188c3a3..04af69c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt
@@ -37,6 +37,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.statusbar.policy.LocationController
 import com.google.common.truth.Truth
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -49,32 +50,23 @@
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
 class NightDisplayTileTest : SysuiTestCase() {
-    @Mock
-    private lateinit var mHost: QSHost
+    @Mock private lateinit var mHost: QSHost
 
-    @Mock
-    private lateinit var mMetricsLogger: MetricsLogger
+    @Mock private lateinit var mMetricsLogger: MetricsLogger
 
-    @Mock
-    private lateinit var mStatusBarStateController: StatusBarStateController
+    @Mock private lateinit var mStatusBarStateController: StatusBarStateController
 
-    @Mock
-    private lateinit var mActivityStarter: ActivityStarter
+    @Mock private lateinit var mActivityStarter: ActivityStarter
 
-    @Mock
-    private lateinit var mQsLogger: QSLogger
+    @Mock private lateinit var mQsLogger: QSLogger
 
-    @Mock
-    private lateinit var mLocationController: LocationController
+    @Mock private lateinit var mLocationController: LocationController
 
-    @Mock
-    private lateinit var mColorDisplayManager: ColorDisplayManager
+    @Mock private lateinit var mColorDisplayManager: ColorDisplayManager
 
-    @Mock
-    private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder
+    @Mock private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder
 
-    @Mock
-    private lateinit var mNightDisplayListener: NightDisplayListener
+    @Mock private lateinit var mNightDisplayListener: NightDisplayListener
 
     private lateinit var mTestableLooper: TestableLooper
     private lateinit var mTile: NightDisplayTile
@@ -88,24 +80,30 @@
         whenever(mHost.context).thenReturn(mContext)
         whenever(mHost.uiEventLogger).thenReturn(mUiEventLogger)
         whenever(mHost.userContext).thenReturn(mContext)
-        whenever(mNightDisplayListenerBuilder.setUser(anyInt())).thenReturn(
-            mNightDisplayListenerBuilder
-        )
+        whenever(mNightDisplayListenerBuilder.setUser(anyInt()))
+            .thenReturn(mNightDisplayListenerBuilder)
         whenever(mNightDisplayListenerBuilder.build()).thenReturn(mNightDisplayListener)
 
-        mTile = NightDisplayTile(
-            mHost,
-            mTestableLooper.looper,
-            Handler(mTestableLooper.looper),
-            FalsingManagerFake(),
-            mMetricsLogger,
-            mStatusBarStateController,
-            mActivityStarter,
-            mQsLogger,
-            mLocationController,
-            mColorDisplayManager,
-            mNightDisplayListenerBuilder
-        )
+        mTile =
+            NightDisplayTile(
+                mHost,
+                mTestableLooper.looper,
+                Handler(mTestableLooper.looper),
+                FalsingManagerFake(),
+                mMetricsLogger,
+                mStatusBarStateController,
+                mActivityStarter,
+                mQsLogger,
+                mLocationController,
+                mColorDisplayManager,
+                mNightDisplayListenerBuilder
+            )
+    }
+
+    @After
+    fun tearDown() {
+        mTile.destroy()
+        mTestableLooper.processAllMessages()
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
index 3344a17..652c138 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
@@ -37,6 +37,7 @@
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.settings.SecureSettings;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -91,6 +92,12 @@
         mTile.initialize();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testIsAvailable_unsupportOneHandedProperty_shouldReturnsFalse() {
         when(mTile.isSupportOneHandedMode()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
index 24287ea..3125d45 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QRCodeScannerTileTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -91,6 +92,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testNewTile() {
         assertFalse(mTile.newTileState().handlesLongClick);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
index 4722c8d..596df78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -73,6 +73,7 @@
 import com.android.systemui.util.settings.SecureSettings;
 import com.android.systemui.wallet.controller.QuickAccessWalletController;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -161,6 +162,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testNewTile() {
         assertFalse(mTile.newTileState().handlesLongClick);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
index 99e5564..7913628 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
@@ -44,8 +44,8 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.settings.UserTracker;
 
+import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -54,7 +54,6 @@
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
-@Ignore("b/269171747")
 public class ReduceBrightColorsTileTest extends SysuiTestCase {
     @Mock
     private QSHost mHost;
@@ -99,6 +98,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testNotActive() {
         when(mReduceBrightColorsController.isReduceBrightColorsActivated()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
index c7eb2f1..5b94cfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/RotationLockTileTest.java
@@ -48,6 +48,7 @@
 import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.wrapper.RotationPolicyWrapper;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -139,6 +140,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mLockTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     @Test
     public void testSecondaryString_cameraRotateOn_returnsFaceBased() {
         assertEquals(mContext.getString(R.string.rotation_lock_camera_rotation_on),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index 21acc08..5aef758 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -50,6 +50,7 @@
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -114,6 +115,12 @@
         mTestableLooper.processAllMessages();
     }
 
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
     // Test that the tile is inactive and labeled correctly when the controller is neither starting
     // or recording, and that clicking on the tile in this state brings up the record prompt
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
index 3d9f650..b556571 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt
@@ -39,6 +39,7 @@
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.LocationController
 import com.google.common.truth.Truth.assertThat
+import org.junit.After
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -98,6 +99,12 @@
             )
     }
 
+    @After
+    fun tearDown() {
+        tile.destroy()
+        testableLooper.processAllMessages()
+    }
+
     @Test
     fun testIcon_whenNightModeOn_isOnState() {
         val state = QSTile.BooleanState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
new file mode 100644
index 0000000..4f469f7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -0,0 +1,754 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.shade;
+
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+
+import static com.android.keyguard.KeyguardClockSwitch.LARGE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
+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.atLeast;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.IdRes;
+import android.content.ContentResolver;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.UserManager;
+import android.util.DisplayMetrics;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.ViewPropertyAnimator;
+import android.view.ViewStub;
+import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.constraintlayout.widget.ConstraintSet;
+
+import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.testing.UiEventLoggerFake;
+import com.android.internal.util.LatencyTracker;
+import com.android.keyguard.KeyguardClockSwitch;
+import com.android.keyguard.KeyguardClockSwitchController;
+import com.android.keyguard.KeyguardStatusView;
+import com.android.keyguard.KeyguardStatusViewController;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.LockIconViewController;
+import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
+import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
+import com.android.keyguard.dagger.KeyguardStatusViewComponent;
+import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.classifier.FalsingCollectorFake;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.common.ui.view.LongPressHandlingView;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository;
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
+import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
+import com.android.systemui.media.controls.pipeline.MediaDataManager;
+import com.android.systemui.media.controls.ui.KeyguardMediaController;
+import com.android.systemui.media.controls.ui.MediaHierarchyManager;
+import com.android.systemui.model.SysUiState;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.shade.transition.ShadeTransitionController;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.NotificationShelfController;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.QsFrameTranslateController;
+import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.ConversationNotificationManager;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.stack.AmbientState;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
+import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
+import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
+import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
+import com.android.systemui.statusbar.phone.TapAgainViewController;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
+import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
+import com.android.systemui.unfold.SysUIUnfoldComponent;
+import com.android.systemui.util.time.FakeSystemClock;
+import com.android.systemui.util.time.SystemClock;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+import java.util.List;
+import java.util.Optional;
+
+import dagger.Lazy;
+import kotlinx.coroutines.CoroutineDispatcher;
+
+public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
+
+    protected static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
+    protected static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
+    protected static final int PANEL_WIDTH = 500; // Random value just for the test.
+
+    @Mock protected CentralSurfaces mCentralSurfaces;
+    @Mock protected NotificationStackScrollLayout mNotificationStackScrollLayout;
+    @Mock protected KeyguardBottomAreaView mKeyguardBottomArea;
+    @Mock protected KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
+    @Mock protected KeyguardBottomAreaView mQsFrame;
+    @Mock protected HeadsUpManagerPhone mHeadsUpManager;
+    @Mock protected NotificationShelfController mNotificationShelfController;
+    @Mock protected NotificationGutsManager mGutsManager;
+    @Mock protected KeyguardStatusBarView mKeyguardStatusBar;
+    @Mock protected KeyguardUserSwitcherView mUserSwitcherView;
+    @Mock protected ViewStub mUserSwitcherStubView;
+    @Mock protected HeadsUpTouchHelper.Callback mHeadsUpCallback;
+    @Mock protected KeyguardUpdateMonitor mUpdateMonitor;
+    @Mock protected KeyguardBypassController mKeyguardBypassController;
+    @Mock protected DozeParameters mDozeParameters;
+    @Mock protected ScreenOffAnimationController mScreenOffAnimationController;
+    @Mock protected NotificationPanelView mView;
+    @Mock protected LayoutInflater mLayoutInflater;
+    @Mock protected FeatureFlags mFeatureFlags;
+    @Mock protected DynamicPrivacyController mDynamicPrivacyController;
+    @Mock protected StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
+    @Mock protected KeyguardStateController mKeyguardStateController;
+    @Mock protected DozeLog mDozeLog;
+    @Mock protected ShadeLogger mShadeLog;
+    @Mock protected ShadeHeightLogger mShadeHeightLogger;
+    @Mock protected CommandQueue mCommandQueue;
+    @Mock protected VibratorHelper mVibratorHelper;
+    @Mock protected LatencyTracker mLatencyTracker;
+    @Mock protected PowerManager mPowerManager;
+    @Mock protected AccessibilityManager mAccessibilityManager;
+    @Mock protected MetricsLogger mMetricsLogger;
+    @Mock protected Resources mResources;
+    @Mock protected Configuration mConfiguration;
+    @Mock protected KeyguardClockSwitch mKeyguardClockSwitch;
+    @Mock protected MediaHierarchyManager mMediaHierarchyManager;
+    @Mock protected ConversationNotificationManager mConversationNotificationManager;
+    @Mock protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    @Mock protected KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
+    @Mock protected KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
+    @Mock protected KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
+    @Mock protected KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
+    @Mock protected KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
+    @Mock protected KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
+    @Mock protected KeyguardUserSwitcherController mKeyguardUserSwitcherController;
+    @Mock protected KeyguardStatusViewComponent mKeyguardStatusViewComponent;
+    @Mock protected KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
+    @Mock protected KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
+    @Mock protected KeyguardClockSwitchController mKeyguardClockSwitchController;
+    @Mock protected KeyguardStatusViewController mKeyguardStatusViewController;
+    @Mock protected KeyguardStatusBarViewController mKeyguardStatusBarViewController;
+    @Mock protected NotificationStackScrollLayoutController
+            mNotificationStackScrollLayoutController;
+    @Mock protected NotificationShadeDepthController mNotificationShadeDepthController;
+    @Mock protected LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+    @Mock protected AuthController mAuthController;
+    @Mock protected ScrimController mScrimController;
+    @Mock protected MediaDataManager mMediaDataManager;
+    @Mock protected AmbientState mAmbientState;
+    @Mock protected UserManager mUserManager;
+    @Mock protected UiEventLogger mUiEventLogger;
+    @Mock protected LockIconViewController mLockIconViewController;
+    @Mock protected KeyguardMediaController mKeyguardMediaController;
+    @Mock protected NavigationModeController mNavigationModeController;
+    @Mock protected NavigationBarController mNavigationBarController;
+    @Mock protected QuickSettingsController mQsController;
+    @Mock protected ShadeHeaderController mShadeHeaderController;
+    @Mock protected ContentResolver mContentResolver;
+    @Mock protected TapAgainViewController mTapAgainViewController;
+    @Mock protected KeyguardIndicationController mKeyguardIndicationController;
+    @Mock protected FragmentService mFragmentService;
+    @Mock protected FragmentHostManager mFragmentHostManager;
+    @Mock protected NotificationRemoteInputManager mNotificationRemoteInputManager;
+    @Mock protected RecordingController mRecordingController;
+    @Mock protected LockscreenGestureLogger mLockscreenGestureLogger;
+    @Mock protected DumpManager mDumpManager;
+    @Mock protected InteractionJankMonitor mInteractionJankMonitor;
+    @Mock protected NotificationsQSContainerController mNotificationsQSContainerController;
+    @Mock protected QsFrameTranslateController mQsFrameTranslateController;
+    @Mock protected StatusBarWindowStateController mStatusBarWindowStateController;
+    @Mock protected KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+    @Mock protected NotificationShadeWindowController mNotificationShadeWindowController;
+    @Mock protected SysUiState mSysUiState;
+    @Mock protected NotificationListContainer mNotificationListContainer;
+    @Mock protected NotificationStackSizeCalculator mNotificationStackSizeCalculator;
+    @Mock protected UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+    @Mock protected ShadeTransitionController mShadeTransitionController;
+    @Mock protected QS mQs;
+    @Mock protected QSFragment mQSFragment;
+    @Mock protected ViewGroup mQsHeader;
+    @Mock protected ViewParent mViewParent;
+    @Mock protected ViewTreeObserver mViewTreeObserver;
+    @Mock protected KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
+    @Mock protected DreamingToLockscreenTransitionViewModel
+            mDreamingToLockscreenTransitionViewModel;
+    @Mock protected OccludedToLockscreenTransitionViewModel
+            mOccludedToLockscreenTransitionViewModel;
+    @Mock protected LockscreenToDreamingTransitionViewModel
+            mLockscreenToDreamingTransitionViewModel;
+    @Mock protected LockscreenToOccludedTransitionViewModel
+            mLockscreenToOccludedTransitionViewModel;
+    @Mock protected GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
+
+    @Mock protected KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+    @Mock protected KeyguardLongPressViewModel mKeyuardLongPressViewModel;
+    @Mock protected AlternateBouncerInteractor mAlternateBouncerInteractor;
+    @Mock protected MotionEvent mDownMotionEvent;
+    @Mock protected CoroutineDispatcher mMainDispatcher;
+    @Captor
+    protected ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
+            mEmptySpaceClickListenerCaptor;
+
+    protected KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
+    protected KeyguardInteractor mKeyguardInteractor;
+    protected NotificationPanelViewController.TouchHandler mTouchHandler;
+    protected ConfigurationController mConfigurationController;
+    protected SysuiStatusBarStateController mStatusBarStateController;
+    protected NotificationPanelViewController mNotificationPanelViewController;
+    protected View.AccessibilityDelegate mAccessibilityDelegate;
+    protected NotificationsQuickSettingsContainer mNotificationContainerParent;
+    protected List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
+    protected Handler mMainHandler;
+    protected View.OnLayoutChangeListener mLayoutChangeListener;
+
+    protected final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
+    protected final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
+    protected final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
+    protected final ShadeExpansionStateManager mShadeExpansionStateManager =
+            new ShadeExpansionStateManager();
+
+    protected QuickSettingsController mQuickSettingsController;
+    @Mock protected Lazy<NotificationPanelViewController> mNotificationPanelViewControllerLazy;
+
+    protected FragmentHostManager.FragmentListener mFragmentListener;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mMainDispatcher = getMainDispatcher();
+        mKeyguardBottomAreaInteractor = new KeyguardBottomAreaInteractor(
+                new FakeKeyguardRepository());
+        mKeyguardInteractor = new KeyguardInteractor(new FakeKeyguardRepository(), mCommandQueue,
+                mFeatureFlags, new FakeKeyguardBouncerRepository());
+        SystemClock systemClock = new FakeSystemClock();
+        mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
+                mInteractionJankMonitor, mShadeExpansionStateManager);
+
+        KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
+        keyguardStatusView.setId(R.id.keyguard_status_view);
+
+        when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
+        when(mHeadsUpCallback.getContext()).thenReturn(mContext);
+        when(mView.getResources()).thenReturn(mResources);
+        when(mView.getWidth()).thenReturn(PANEL_WIDTH);
+        when(mResources.getConfiguration()).thenReturn(mConfiguration);
+        mConfiguration.orientation = ORIENTATION_PORTRAIT;
+        when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
+        mDisplayMetrics.density = 100;
+        when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
+        when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
+                .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
+        when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
+                .thenReturn(10);
+        when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
+                .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
+        when(mView.getContext()).thenReturn(getContext());
+        when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
+        when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
+        when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
+                mUserSwitcherStubView);
+        when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
+        when(mView.findViewById(R.id.notification_stack_scroller))
+                .thenReturn(mNotificationStackScrollLayout);
+        when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
+        when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
+                .thenReturn(mHeadsUpCallback);
+        when(mKeyguardBottomAreaViewController.getView()).thenReturn(mKeyguardBottomArea);
+        when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
+        when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class));
+        when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
+        when(mView.findViewById(R.id.keyguard_status_view))
+                .thenReturn(mock(KeyguardStatusView.class));
+        mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
+        mNotificationContainerParent.addView(keyguardStatusView);
+        mNotificationContainerParent.onFinishInflate();
+        when(mView.findViewById(R.id.notification_container_parent))
+                .thenReturn(mNotificationContainerParent);
+        when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
+        FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
+                mDisplayMetrics);
+        when(mKeyguardQsUserSwitchComponentFactory.build(any()))
+                .thenReturn(mKeyguardQsUserSwitchComponent);
+        when(mKeyguardQsUserSwitchComponent.getKeyguardQsUserSwitchController())
+                .thenReturn(mKeyguardQsUserSwitchController);
+        when(mKeyguardUserSwitcherComponentFactory.build(any()))
+                .thenReturn(mKeyguardUserSwitcherComponent);
+        when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
+                .thenReturn(mKeyguardUserSwitcherController);
+        when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
+        when(mQs.getView()).thenReturn(mView);
+        when(mQSFragment.getView()).thenReturn(mView);
+        doAnswer(invocation -> {
+            mFragmentListener = invocation.getArgument(1);
+            return null;
+        }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any());
+        doAnswer((Answer<Void>) invocation -> {
+            mTouchHandler = invocation.getArgument(0);
+            return null;
+        }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
+
+        // Dreaming->Lockscreen
+        when(mKeyguardTransitionInteractor.getDreamingToLockscreenTransition())
+                .thenReturn(emptyFlow());
+        when(mDreamingToLockscreenTransitionViewModel.getLockscreenAlpha())
+                .thenReturn(emptyFlow());
+        when(mDreamingToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
+                .thenReturn(emptyFlow());
+
+        // Occluded->Lockscreen
+        when(mKeyguardTransitionInteractor.getOccludedToLockscreenTransition())
+                .thenReturn(emptyFlow());
+        when(mOccludedToLockscreenTransitionViewModel.getLockscreenAlpha())
+                .thenReturn(emptyFlow());
+        when(mOccludedToLockscreenTransitionViewModel.lockscreenTranslationY(anyInt()))
+                .thenReturn(emptyFlow());
+
+        // Lockscreen->Dreaming
+        when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
+                .thenReturn(emptyFlow());
+        when(mLockscreenToDreamingTransitionViewModel.getLockscreenAlpha())
+                .thenReturn(emptyFlow());
+        when(mLockscreenToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
+                .thenReturn(emptyFlow());
+
+        // Gone->Dreaming
+        when(mKeyguardTransitionInteractor.getGoneToDreamingTransition())
+                .thenReturn(emptyFlow());
+        when(mGoneToDreamingTransitionViewModel.getLockscreenAlpha())
+                .thenReturn(emptyFlow());
+        when(mGoneToDreamingTransitionViewModel.lockscreenTranslationY(anyInt()))
+                .thenReturn(emptyFlow());
+
+        // Lockscreen->Occluded
+        when(mKeyguardTransitionInteractor.getLockscreenToOccludedTransition())
+                .thenReturn(emptyFlow());
+        when(mLockscreenToOccludedTransitionViewModel.getLockscreenAlpha())
+                .thenReturn(emptyFlow());
+        when(mLockscreenToOccludedTransitionViewModel.lockscreenTranslationY(anyInt()))
+                .thenReturn(emptyFlow());
+
+        NotificationWakeUpCoordinator coordinator =
+                new NotificationWakeUpCoordinator(
+                        mDumpManager,
+                        mock(HeadsUpManagerPhone.class),
+                        new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
+                                mInteractionJankMonitor, mShadeExpansionStateManager),
+                        mKeyguardBypassController,
+                        mDozeParameters,
+                        mScreenOffAnimationController,
+                        mock(NotificationWakeUpCoordinatorLogger.class));
+        mConfigurationController = new ConfigurationControllerImpl(mContext);
+        PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
+                mContext,
+                coordinator,
+                mKeyguardBypassController, mHeadsUpManager,
+                mock(NotificationRoundnessManager.class),
+                mConfigurationController,
+                mStatusBarStateController,
+                mFalsingManager,
+                mShadeExpansionStateManager,
+                mLockscreenShadeTransitionController,
+                new FalsingCollectorFake(),
+                mDumpManager);
+        when(mKeyguardStatusViewComponentFactory.build(any()))
+                .thenReturn(mKeyguardStatusViewComponent);
+        when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
+                .thenReturn(mKeyguardClockSwitchController);
+        when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
+                .thenReturn(mKeyguardStatusViewController);
+        when(mKeyguardStatusBarViewComponentFactory.build(any(), any()))
+                .thenReturn(mKeyguardStatusBarViewComponent);
+        when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
+                .thenReturn(mKeyguardStatusBarViewController);
+        when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
+                .thenReturn(keyguardStatusView);
+        when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
+                .thenReturn(mUserSwitcherView);
+        when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
+                .thenReturn(mKeyguardBottomArea);
+        when(mNotificationRemoteInputManager.isRemoteInputActive())
+                .thenReturn(false);
+        when(mInteractionJankMonitor.begin(any(), anyInt()))
+                .thenReturn(true);
+        when(mInteractionJankMonitor.end(anyInt()))
+                .thenReturn(true);
+        doAnswer(invocation -> {
+            ((Runnable) invocation.getArgument(0)).run();
+            return null;
+        }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
+        doAnswer(invocation -> {
+            mLayoutChangeListener = invocation.getArgument(0);
+            return null;
+        }).when(mView).addOnLayoutChangeListener(any());
+
+        when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
+        when(mView.getParent()).thenReturn(mViewParent);
+        when(mQs.getHeader()).thenReturn(mQsHeader);
+        when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN);
+        when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
+
+        mMainHandler = new Handler(Looper.getMainLooper());
+
+        when(mView.requireViewById(R.id.keyguard_long_press))
+                .thenReturn(mock(LongPressHandlingView.class));
+
+        mNotificationPanelViewController = new NotificationPanelViewController(
+                mView,
+                mMainHandler,
+                mLayoutInflater,
+                mFeatureFlags,
+                coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
+                mFalsingManager, new FalsingCollectorFake(),
+                mKeyguardStateController,
+                mStatusBarStateController,
+                mStatusBarWindowStateController,
+                mNotificationShadeWindowController,
+                mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper,
+                mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
+                mMetricsLogger,
+                mShadeLog,
+                mShadeHeightLogger,
+                mConfigurationController,
+                () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
+                mConversationNotificationManager, mMediaHierarchyManager,
+                mStatusBarKeyguardViewManager,
+                mGutsManager,
+                mNotificationsQSContainerController,
+                mNotificationStackScrollLayoutController,
+                mKeyguardStatusViewComponentFactory,
+                mKeyguardQsUserSwitchComponentFactory,
+                mKeyguardUserSwitcherComponentFactory,
+                mKeyguardStatusBarViewComponentFactory,
+                mLockscreenShadeTransitionController,
+                mAuthController,
+                mScrimController,
+                mUserManager,
+                mMediaDataManager,
+                mNotificationShadeDepthController,
+                mAmbientState,
+                mLockIconViewController,
+                mKeyguardMediaController,
+                mTapAgainViewController,
+                mNavigationModeController,
+                mNavigationBarController,
+                mQsController,
+                mFragmentService,
+                mContentResolver,
+                mRecordingController,
+                mShadeHeaderController,
+                mScreenOffAnimationController,
+                mLockscreenGestureLogger,
+                mShadeExpansionStateManager,
+                mNotificationRemoteInputManager,
+                mSysUIUnfoldComponent,
+                mSysUiState,
+                () -> mKeyguardBottomAreaViewController,
+                mKeyguardUnlockAnimationController,
+                mKeyguardIndicationController,
+                mNotificationListContainer,
+                mNotificationStackSizeCalculator,
+                mUnlockedScreenOffAnimationController,
+                mShadeTransitionController,
+                mInteractionJankMonitor,
+                systemClock,
+                mKeyguardBottomAreaViewModel,
+                mKeyguardBottomAreaInteractor,
+                mAlternateBouncerInteractor,
+                mDreamingToLockscreenTransitionViewModel,
+                mOccludedToLockscreenTransitionViewModel,
+                mLockscreenToDreamingTransitionViewModel,
+                mGoneToDreamingTransitionViewModel,
+                mLockscreenToOccludedTransitionViewModel,
+                mMainDispatcher,
+                mKeyguardTransitionInteractor,
+                mDumpManager,
+                mKeyuardLongPressViewModel,
+                mKeyguardInteractor);
+        mNotificationPanelViewController.initDependencies(
+                mCentralSurfaces,
+                null,
+                () -> {},
+                mNotificationShelfController);
+        mNotificationPanelViewController.setTrackingStartedListener(() -> {});
+        mNotificationPanelViewController.setOpenCloseListener(
+                new NotificationPanelViewController.OpenCloseListener() {
+                    @Override
+                    public void onClosingFinished() {}
+
+                    @Override
+                    public void onOpenStarted() {}
+                });
+        mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
+        ArgumentCaptor<View.OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
+                ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
+        verify(mView, atLeast(1)).addOnAttachStateChangeListener(
+                onAttachStateChangeListenerArgumentCaptor.capture());
+        mOnAttachStateChangeListeners = onAttachStateChangeListenerArgumentCaptor.getAllValues();
+
+        ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
+                ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
+        verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
+        mAccessibilityDelegate = accessibilityDelegateArgumentCaptor.getValue();
+        mNotificationPanelViewController.getStatusBarStateController()
+                .addCallback(mNotificationPanelViewController.getStatusBarStateListener());
+        mNotificationPanelViewController
+                .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
+        verify(mNotificationStackScrollLayoutController)
+                .setOnEmptySpaceClickListener(mEmptySpaceClickListenerCaptor.capture());
+        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
+        reset(mKeyguardStatusViewController);
+
+        when(mNotificationPanelViewControllerLazy.get())
+                .thenReturn(mNotificationPanelViewController);
+        mQuickSettingsController = new QuickSettingsController(
+                mNotificationPanelViewControllerLazy,
+                mView,
+                mQsFrameTranslateController,
+                mShadeTransitionController,
+                expansionHandler,
+                mNotificationRemoteInputManager,
+                mShadeExpansionStateManager,
+                mStatusBarKeyguardViewManager,
+                mNotificationStackScrollLayoutController,
+                mLockscreenShadeTransitionController,
+                mNotificationShadeDepthController,
+                mShadeHeaderController,
+                mStatusBarTouchableRegionManager,
+                mKeyguardStateController,
+                mKeyguardBypassController,
+                mUpdateMonitor,
+                mScrimController,
+                mMediaDataManager,
+                mMediaHierarchyManager,
+                mAmbientState,
+                mRecordingController,
+                mFalsingManager,
+                new FalsingCollectorFake(),
+                mAccessibilityManager,
+                mLockscreenGestureLogger,
+                mMetricsLogger,
+                mFeatureFlags,
+                mInteractionJankMonitor,
+                mShadeLog
+        );
+    }
+
+    @After
+    public void tearDown() {
+        mNotificationPanelViewController.mBottomAreaShadeAlphaAnimator.cancel();
+        mNotificationPanelViewController.cancelHeightAnimator();
+        mMainHandler.removeCallbacksAndMessages(null);
+    }
+
+    protected void setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding,
+            int ambientPadding) {
+
+        when(mNotificationStackScrollLayoutController.getTop()).thenReturn(0);
+        when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(stackBottom);
+        when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
+        when(mLockIconViewController.getTop()).thenReturn((float) (stackBottom - lockIconPadding));
+
+        when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
+                .thenReturn(indicationPadding);
+        mNotificationPanelViewController.loadDimens();
+
+        mNotificationPanelViewController.setAmbientIndicationTop(
+                /* ambientIndicationTop= */ stackBottom - ambientPadding,
+                /* ambientTextVisible= */ true);
+    }
+
+    protected void triggerPositionClockAndNotifications() {
+        mNotificationPanelViewController.onQsSetExpansionHeightCalled(false);
+    }
+
+    protected FalsingManager.FalsingTapListener getFalsingTapListener() {
+        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
+            listener.onViewAttachedToWindow(mView);
+        }
+        assertThat(mFalsingManager.getTapListeners().size()).isEqualTo(1);
+        return mFalsingManager.getTapListeners().get(0);
+    }
+
+    protected void givenViewAttached() {
+        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
+            listener.onViewAttachedToWindow(mView);
+        }
+    }
+
+    protected ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
+        ConstraintSet constraintSet = new ConstraintSet();
+        constraintSet.clone(mNotificationContainerParent);
+        return constraintSet.getConstraint(id).layout;
+    }
+
+    protected void enableSplitShade(boolean enabled) {
+        when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
+        mNotificationPanelViewController.updateResources();
+    }
+
+    protected void updateMultiUserSetting(boolean enabled) {
+        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
+        when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
+        final ArgumentCaptor<ContentObserver> observerCaptor =
+                ArgumentCaptor.forClass(ContentObserver.class);
+        verify(mContentResolver)
+                .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
+        observerCaptor.getValue().onChange(/* selfChange */ false);
+    }
+
+    protected void updateSmallestScreenWidth(int smallestScreenWidthDp) {
+        Configuration configuration = new Configuration();
+        configuration.smallestScreenWidthDp = smallestScreenWidthDp;
+        mConfigurationController.onConfigurationChanged(configuration);
+    }
+
+    protected void onTouchEvent(MotionEvent ev) {
+        mTouchHandler.onTouch(mView, ev);
+    }
+
+    protected void setDozing(boolean dozing, boolean dozingAlwaysOn) {
+        when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
+        mNotificationPanelViewController.setDozing(
+                /* dozing= */ dozing,
+                /* animate= */ false
+        );
+    }
+
+    protected void assertKeyguardStatusViewCentered() {
+        mNotificationPanelViewController.updateResources();
+        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isAnyOf(
+                ConstraintSet.PARENT_ID, ConstraintSet.UNSET);
+    }
+
+    protected void assertKeyguardStatusViewNotCentered() {
+        mNotificationPanelViewController.updateResources();
+        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
+                R.id.qs_edge_guideline);
+    }
+
+    protected void setIsFullWidth(boolean fullWidth) {
+        float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
+        when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
+        triggerLayoutChange();
+    }
+
+    protected void triggerLayoutChange() {
+        mLayoutChangeListener.onLayoutChange(
+                mView,
+                /* left= */ 0,
+                /* top= */ 0,
+                /* right= */ 0,
+                /* bottom= */ 0,
+                /* oldLeft= */ 0,
+                /* oldTop= */ 0,
+                /* oldRight= */ 0,
+                /* oldBottom= */ 0
+        );
+    }
+
+    protected CoroutineDispatcher getMainDispatcher() {
+        return mMainDispatcher;
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 8f6653f..d86ff67 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.shade;
 
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-
 import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
 import static com.android.keyguard.KeyguardClockSwitch.LARGE;
 import static com.android.keyguard.KeyguardClockSwitch.SMALL;
@@ -31,592 +29,72 @@
 import static com.google.common.truth.Truth.assertThat;
 
 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.anyString;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.annotation.IdRes;
-import android.content.ContentResolver;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PowerManager;
-import android.os.UserManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
-import android.util.DisplayMetrics;
-import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-import android.view.ViewPropertyAnimator;
-import android.view.ViewStub;
-import android.view.ViewTreeObserver;
-import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 import androidx.constraintlayout.widget.ConstraintSet;
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.testing.UiEventLoggerFake;
-import com.android.internal.util.CollectionUtils;
-import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.FaceAuthApiRequestReason;
-import com.android.keyguard.KeyguardClockSwitch;
-import com.android.keyguard.KeyguardClockSwitchController;
-import com.android.keyguard.KeyguardStatusView;
-import com.android.keyguard.KeyguardStatusViewController;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.LockIconViewController;
-import com.android.keyguard.dagger.KeyguardQsUserSwitchComponent;
-import com.android.keyguard.dagger.KeyguardStatusBarViewComponent;
-import com.android.keyguard.dagger.KeyguardStatusViewComponent;
-import com.android.keyguard.dagger.KeyguardUserSwitcherComponent;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.classifier.FalsingCollectorFake;
-import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.common.ui.view.LongPressHandlingView;
-import com.android.systemui.doze.DozeLog;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.fragments.FragmentHostManager;
-import com.android.systemui.fragments.FragmentService;
-import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
-import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
-import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
-import com.android.systemui.keyguard.ui.viewmodel.OccludedToLockscreenTransitionViewModel;
-import com.android.systemui.media.controls.pipeline.MediaDataManager;
-import com.android.systemui.media.controls.ui.KeyguardMediaController;
-import com.android.systemui.media.controls.ui.MediaHierarchyManager;
-import com.android.systemui.model.SysUiState;
-import com.android.systemui.navigationbar.NavigationBarController;
-import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSFragment;
-import com.android.systemui.screenrecord.RecordingController;
-import com.android.systemui.shade.transition.ShadeTransitionController;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.NotificationShelfController;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.QsFrameTranslateController;
-import com.android.systemui.statusbar.StatusBarStateControllerImpl;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.VibratorHelper;
-import com.android.systemui.statusbar.notification.ConversationNotificationManager;
-import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinatorLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.AmbientState;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.notification.stack.NotificationRoundnessManager;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.notification.stack.NotificationStackSizeCalculator;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaViewController;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
-import com.android.systemui.statusbar.phone.KeyguardStatusBarViewController;
-import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
-import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
-import com.android.systemui.statusbar.phone.TapAgainViewController;
-import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.KeyguardQsUserSwitchController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController;
-import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView;
-import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.unfold.SysUIUnfoldComponent;
-import com.android.systemui.util.time.FakeSystemClock;
-import com.android.systemui.util.time.SystemClock;
-import com.android.wm.shell.animation.FlingAnimationUtils;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
 import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
 
 import java.util.List;
-import java.util.Optional;
-
-import dagger.Lazy;
-import kotlinx.coroutines.CoroutineDispatcher;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
-public class NotificationPanelViewControllerTest extends SysuiTestCase {
-
-    private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
-    private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
-    private static final int PANEL_WIDTH = 500; // Random value just for the test.
-
-    @Mock private CentralSurfaces mCentralSurfaces;
-    @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout;
-    @Mock private KeyguardBottomAreaView mKeyguardBottomArea;
-    @Mock private KeyguardBottomAreaViewController mKeyguardBottomAreaViewController;
-    @Mock private KeyguardBottomAreaView mQsFrame;
-    @Mock private HeadsUpManagerPhone mHeadsUpManager;
-    @Mock private NotificationShelfController mNotificationShelfController;
-    @Mock private NotificationGutsManager mGutsManager;
-    @Mock private KeyguardStatusBarView mKeyguardStatusBar;
-    @Mock private KeyguardUserSwitcherView mUserSwitcherView;
-    @Mock private ViewStub mUserSwitcherStubView;
-    @Mock private HeadsUpTouchHelper.Callback mHeadsUpCallback;
-    @Mock private KeyguardUpdateMonitor mUpdateMonitor;
-    @Mock private KeyguardBypassController mKeyguardBypassController;
-    @Mock private DozeParameters mDozeParameters;
-    @Mock private ScreenOffAnimationController mScreenOffAnimationController;
-    @Mock private NotificationPanelView mView;
-    @Mock private LayoutInflater mLayoutInflater;
-    @Mock private FeatureFlags mFeatureFlags;
-    @Mock private DynamicPrivacyController mDynamicPrivacyController;
-    @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
-    @Mock private KeyguardStateController mKeyguardStateController;
-    @Mock private DozeLog mDozeLog;
-    @Mock private ShadeLogger mShadeLog;
-    @Mock private ShadeHeightLogger mShadeHeightLogger;
-    @Mock private CommandQueue mCommandQueue;
-    @Mock private VibratorHelper mVibratorHelper;
-    @Mock private LatencyTracker mLatencyTracker;
-    @Mock private PowerManager mPowerManager;
-    @Mock private AccessibilityManager mAccessibilityManager;
-    @Mock private MetricsLogger mMetricsLogger;
-    @Mock private Resources mResources;
-    @Mock private Configuration mConfiguration;
-    @Mock private KeyguardClockSwitch mKeyguardClockSwitch;
-    @Mock private MediaHierarchyManager mMediaHierarchyManager;
-    @Mock private ConversationNotificationManager mConversationNotificationManager;
-    @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-    @Mock private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
-    @Mock private KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory;
-    @Mock private KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent;
-    @Mock private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController;
-    @Mock private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory;
-    @Mock private KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent;
-    @Mock private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
-    @Mock private KeyguardStatusViewComponent mKeyguardStatusViewComponent;
-    @Mock private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory;
-    @Mock private KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent;
-    @Mock private KeyguardClockSwitchController mKeyguardClockSwitchController;
-    @Mock private KeyguardStatusViewController mKeyguardStatusViewController;
-    @Mock private KeyguardStatusBarViewController mKeyguardStatusBarViewController;
-    @Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
-    @Mock private NotificationShadeDepthController mNotificationShadeDepthController;
-    @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController;
-    @Mock private AuthController mAuthController;
-    @Mock private ScrimController mScrimController;
-    @Mock private MediaDataManager mMediaDataManager;
-    @Mock private AmbientState mAmbientState;
-    @Mock private UserManager mUserManager;
-    @Mock private UiEventLogger mUiEventLogger;
-    @Mock private LockIconViewController mLockIconViewController;
-    @Mock private KeyguardMediaController mKeyguardMediaController;
-    @Mock private NavigationModeController mNavigationModeController;
-    @Mock private NavigationBarController mNavigationBarController;
-    @Mock private QuickSettingsController mQsController;
-    @Mock private ShadeHeaderController mShadeHeaderController;
-    @Mock private ContentResolver mContentResolver;
-    @Mock private TapAgainViewController mTapAgainViewController;
-    @Mock private KeyguardIndicationController mKeyguardIndicationController;
-    @Mock private FragmentService mFragmentService;
-    @Mock private FragmentHostManager mFragmentHostManager;
-    @Mock private NotificationRemoteInputManager mNotificationRemoteInputManager;
-    @Mock private RecordingController mRecordingController;
-    @Mock private LockscreenGestureLogger mLockscreenGestureLogger;
-    @Mock private DumpManager mDumpManager;
-    @Mock private InteractionJankMonitor mInteractionJankMonitor;
-    @Mock private NotificationsQSContainerController mNotificationsQSContainerController;
-    @Mock private QsFrameTranslateController mQsFrameTranslateController;
-    @Mock private StatusBarWindowStateController mStatusBarWindowStateController;
-    @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
-    @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
-    @Mock private SysUiState mSysUiState;
-    @Mock private NotificationListContainer mNotificationListContainer;
-    @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
-    @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
-    @Mock private ShadeTransitionController mShadeTransitionController;
-    @Mock private QS mQs;
-    @Mock private QSFragment mQSFragment;
-    @Mock private ViewGroup mQsHeader;
-    @Mock private ViewParent mViewParent;
-    @Mock private ViewTreeObserver mViewTreeObserver;
-    @Mock private KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel;
-    @Mock private KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
-    @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
-    @Mock private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
-    @Mock private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
-    @Mock private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
-    @Mock private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
-    @Mock private GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
-
-    @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
-    @Mock private KeyguardInteractor mKeyguardInteractor;
-    @Mock private KeyguardLongPressViewModel mKeyuardLongPressViewModel;
-    @Mock private CoroutineDispatcher mMainDispatcher;
-    @Mock private MotionEvent mDownMotionEvent;
-    @Captor
-    private ArgumentCaptor<NotificationStackScrollLayout.OnEmptySpaceClickListener>
-            mEmptySpaceClickListenerCaptor;
-
-    private NotificationPanelViewController.TouchHandler mTouchHandler;
-    private ConfigurationController mConfigurationController;
-    private SysuiStatusBarStateController mStatusBarStateController;
-    private NotificationPanelViewController mNotificationPanelViewController;
-    private View.AccessibilityDelegate mAccessibilityDelegate;
-    private NotificationsQuickSettingsContainer mNotificationContainerParent;
-    private List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
-    private Handler mMainHandler;
-    private View.OnLayoutChangeListener mLayoutChangeListener;
-
-    private final FalsingManagerFake mFalsingManager = new FalsingManagerFake();
-    private final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty();
-    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
-    private final ShadeExpansionStateManager mShadeExpansionStateManager =
-            new ShadeExpansionStateManager();
-
-    private QuickSettingsController mQuickSettingsController;
-    @Mock private Lazy<NotificationPanelViewController> mNotificationPanelViewControllerLazy;
-
-    private FragmentHostManager.FragmentListener mFragmentListener;
+public class NotificationPanelViewControllerTest extends NotificationPanelViewControllerBaseTest {
 
     @Before
-    public void setup() {
-        MockitoAnnotations.initMocks(this);
-        SystemClock systemClock = new FakeSystemClock();
-        mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager,
-                mInteractionJankMonitor, mShadeExpansionStateManager);
-
-        KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext);
-        keyguardStatusView.setId(R.id.keyguard_status_view);
+    public void before() {
         DejankUtils.setImmediate(true);
-
-        when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
-        when(mHeadsUpCallback.getContext()).thenReturn(mContext);
-        when(mView.getResources()).thenReturn(mResources);
-        when(mView.getWidth()).thenReturn(PANEL_WIDTH);
-        when(mResources.getConfiguration()).thenReturn(mConfiguration);
-        mConfiguration.orientation = ORIENTATION_PORTRAIT;
-        when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
-        mDisplayMetrics.density = 100;
-        when(mResources.getBoolean(R.bool.config_enableNotificationShadeDrag)).thenReturn(true);
-        when(mResources.getDimensionPixelSize(R.dimen.notifications_top_padding_split_shade))
-                .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
-        when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
-                .thenReturn(10);
-        when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
-                .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
-        when(mView.getContext()).thenReturn(getContext());
-        when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
-        when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
-        when(mView.findViewById(R.id.keyguard_user_switcher_stub)).thenReturn(
-                mUserSwitcherStubView);
-        when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
-        when(mView.findViewById(R.id.notification_stack_scroller))
-                .thenReturn(mNotificationStackScrollLayout);
-        when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
-        when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
-                .thenReturn(mHeadsUpCallback);
-        when(mKeyguardBottomAreaViewController.getView()).thenReturn(mKeyguardBottomArea);
-        when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
-        when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class));
-        when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
-        when(mView.findViewById(R.id.keyguard_status_view))
-                .thenReturn(mock(KeyguardStatusView.class));
-        mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
-        mNotificationContainerParent.addView(keyguardStatusView);
-        mNotificationContainerParent.onFinishInflate();
-        when(mView.findViewById(R.id.notification_container_parent))
-                .thenReturn(mNotificationContainerParent);
-        when(mFragmentService.getFragmentHostManager(mView)).thenReturn(mFragmentHostManager);
-        FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
-                mDisplayMetrics);
-        when(mKeyguardQsUserSwitchComponentFactory.build(any()))
-                .thenReturn(mKeyguardQsUserSwitchComponent);
-        when(mKeyguardQsUserSwitchComponent.getKeyguardQsUserSwitchController())
-                .thenReturn(mKeyguardQsUserSwitchController);
-        when(mKeyguardUserSwitcherComponentFactory.build(any()))
-                .thenReturn(mKeyguardUserSwitcherComponent);
-        when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController())
-                .thenReturn(mKeyguardUserSwitcherController);
-        when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true);
-        when(mQs.getView()).thenReturn(mView);
-        when(mQSFragment.getView()).thenReturn(mView);
-        doAnswer(invocation -> {
-            mFragmentListener = invocation.getArgument(1);
-            return null;
-        }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any());
-        doAnswer((Answer<Void>) invocation -> {
-            mTouchHandler = invocation.getArgument(0);
-            return null;
-        }).when(mView).setOnTouchListener(any(NotificationPanelViewController.TouchHandler.class));
-
-        NotificationWakeUpCoordinator coordinator =
-                new NotificationWakeUpCoordinator(
-                        mDumpManager,
-                        mock(HeadsUpManagerPhone.class),
-                        new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
-                                mInteractionJankMonitor, mShadeExpansionStateManager),
-                        mKeyguardBypassController,
-                        mDozeParameters,
-                        mScreenOffAnimationController,
-                        mock(NotificationWakeUpCoordinatorLogger.class));
-        mConfigurationController = new ConfigurationControllerImpl(mContext);
-        PulseExpansionHandler expansionHandler = new PulseExpansionHandler(
-                mContext,
-                coordinator,
-                mKeyguardBypassController, mHeadsUpManager,
-                mock(NotificationRoundnessManager.class),
-                mConfigurationController,
-                mStatusBarStateController,
-                mFalsingManager,
-                mShadeExpansionStateManager,
-                mLockscreenShadeTransitionController,
-                new FalsingCollectorFake(),
-                mDumpManager);
-        when(mKeyguardStatusViewComponentFactory.build(any()))
-                .thenReturn(mKeyguardStatusViewComponent);
-        when(mKeyguardStatusViewComponent.getKeyguardClockSwitchController())
-                .thenReturn(mKeyguardClockSwitchController);
-        when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
-                .thenReturn(mKeyguardStatusViewController);
-        when(mKeyguardStatusBarViewComponentFactory.build(any(), any()))
-                .thenReturn(mKeyguardStatusBarViewComponent);
-        when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController())
-                .thenReturn(mKeyguardStatusBarViewController);
-        when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean()))
-                .thenReturn(keyguardStatusView);
-        when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean()))
-                .thenReturn(mUserSwitcherView);
-        when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean()))
-                .thenReturn(mKeyguardBottomArea);
-        when(mNotificationRemoteInputManager.isRemoteInputActive())
-                .thenReturn(false);
-        when(mInteractionJankMonitor.begin(any(), anyInt()))
-                .thenReturn(true);
-        when(mInteractionJankMonitor.end(anyInt()))
-                .thenReturn(true);
-        doAnswer(invocation -> {
-            ((Runnable) invocation.getArgument(0)).run();
-            return null;
-        }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any());
-        doAnswer(invocation -> {
-            mLayoutChangeListener = invocation.getArgument(0);
-            return null;
-        }).when(mView).addOnLayoutChangeListener(any());
-
-        when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
-        when(mView.getParent()).thenReturn(mViewParent);
-        when(mQs.getHeader()).thenReturn(mQsHeader);
-        when(mDownMotionEvent.getAction()).thenReturn(MotionEvent.ACTION_DOWN);
-        when(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState);
-
-        mMainHandler = new Handler(Looper.getMainLooper());
-
-        when(mView.requireViewById(R.id.keyguard_long_press))
-                .thenReturn(mock(LongPressHandlingView.class));
-
-        mNotificationPanelViewController = new NotificationPanelViewController(
-                mView,
-                mMainHandler,
-                mLayoutInflater,
-                mFeatureFlags,
-                coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController,
-                mFalsingManager, new FalsingCollectorFake(),
-                mKeyguardStateController,
-                mStatusBarStateController,
-                mStatusBarWindowStateController,
-                mNotificationShadeWindowController,
-                mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper,
-                mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
-                mMetricsLogger,
-                mShadeLog,
-                mShadeHeightLogger,
-                mConfigurationController,
-                () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager,
-                mConversationNotificationManager, mMediaHierarchyManager,
-                mStatusBarKeyguardViewManager,
-                mGutsManager,
-                mNotificationsQSContainerController,
-                mNotificationStackScrollLayoutController,
-                mKeyguardStatusViewComponentFactory,
-                mKeyguardQsUserSwitchComponentFactory,
-                mKeyguardUserSwitcherComponentFactory,
-                mKeyguardStatusBarViewComponentFactory,
-                mLockscreenShadeTransitionController,
-                mAuthController,
-                mScrimController,
-                mUserManager,
-                mMediaDataManager,
-                mNotificationShadeDepthController,
-                mAmbientState,
-                mLockIconViewController,
-                mKeyguardMediaController,
-                mTapAgainViewController,
-                mNavigationModeController,
-                mNavigationBarController,
-                mQsController,
-                mFragmentService,
-                mContentResolver,
-                mRecordingController,
-                mShadeHeaderController,
-                mScreenOffAnimationController,
-                mLockscreenGestureLogger,
-                mShadeExpansionStateManager,
-                mNotificationRemoteInputManager,
-                mSysUIUnfoldComponent,
-                mSysUiState,
-                () -> mKeyguardBottomAreaViewController,
-                mKeyguardUnlockAnimationController,
-                mKeyguardIndicationController,
-                mNotificationListContainer,
-                mNotificationStackSizeCalculator,
-                mUnlockedScreenOffAnimationController,
-                mShadeTransitionController,
-                systemClock,
-                mKeyguardBottomAreaViewModel,
-                mKeyguardBottomAreaInteractor,
-                mAlternateBouncerInteractor,
-                mDreamingToLockscreenTransitionViewModel,
-                mOccludedToLockscreenTransitionViewModel,
-                mLockscreenToDreamingTransitionViewModel,
-                mGoneToDreamingTransitionViewModel,
-                mLockscreenToOccludedTransitionViewModel,
-                mMainDispatcher,
-                mKeyguardTransitionInteractor,
-                mDumpManager,
-                mKeyuardLongPressViewModel,
-                mKeyguardInteractor);
-        mNotificationPanelViewController.initDependencies(
-                mCentralSurfaces,
-                null,
-                () -> {},
-                mNotificationShelfController);
-        mNotificationPanelViewController.setTrackingStartedListener(() -> {});
-        mNotificationPanelViewController.setOpenCloseListener(
-                new NotificationPanelViewController.OpenCloseListener() {
-                    @Override
-                    public void onClosingFinished() {}
-
-                    @Override
-                    public void onOpenStarted() {}
-                });
-        mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
-        ArgumentCaptor<View.OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
-                ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
-        verify(mView, atLeast(1)).addOnAttachStateChangeListener(
-                onAttachStateChangeListenerArgumentCaptor.capture());
-        mOnAttachStateChangeListeners = onAttachStateChangeListenerArgumentCaptor.getAllValues();
-
-        ArgumentCaptor<View.AccessibilityDelegate> accessibilityDelegateArgumentCaptor =
-                ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
-        verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
-        mAccessibilityDelegate = accessibilityDelegateArgumentCaptor.getValue();
-        mNotificationPanelViewController.getStatusBarStateController()
-                .addCallback(mNotificationPanelViewController.getStatusBarStateListener());
-        mNotificationPanelViewController
-                .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
-        verify(mNotificationStackScrollLayoutController)
-                .setOnEmptySpaceClickListener(mEmptySpaceClickListenerCaptor.capture());
-        verify(mKeyguardStatusViewController).displayClock(LARGE, /* animate */ true);
-        reset(mKeyguardStatusViewController);
-
-        when(mNotificationPanelViewControllerLazy.get())
-                .thenReturn(mNotificationPanelViewController);
-        mQuickSettingsController = new QuickSettingsController(
-                mNotificationPanelViewControllerLazy,
-                mView,
-                mQsFrameTranslateController,
-                mShadeTransitionController,
-                expansionHandler,
-                mNotificationRemoteInputManager,
-                mShadeExpansionStateManager,
-                mStatusBarKeyguardViewManager,
-                mNotificationStackScrollLayoutController,
-                mLockscreenShadeTransitionController,
-                mNotificationShadeDepthController,
-                mShadeHeaderController,
-                mStatusBarTouchableRegionManager,
-                mKeyguardStateController,
-                mKeyguardBypassController,
-                mUpdateMonitor,
-                mScrimController,
-                mMediaDataManager,
-                mMediaHierarchyManager,
-                mAmbientState,
-                mRecordingController,
-                mFalsingManager,
-                new FalsingCollectorFake(),
-                mAccessibilityManager,
-                mLockscreenGestureLogger,
-                mMetricsLogger,
-                mFeatureFlags,
-                mInteractionJankMonitor,
-                mShadeLog
-        );
     }
 
-    @After
-    public void tearDown() {
-        mNotificationPanelViewController.cancelHeightAnimator();
-        mMainHandler.removeCallbacksAndMessages(null);
+    /**
+     * When the Back gesture starts (progress 0%), the scrim will stay at 100% scale (1.0f).
+     */
+    @Test
+    public void testBackGesture_min_scrimAtMaxScale() {
+        mNotificationPanelViewController.onBackProgressed(0.0f);
+        verify(mScrimController).applyBackScaling(1.0f);
+    }
+
+    /**
+     * When the Back gesture is at max (progress 100%), the scrim will be scaled to its minimum.
+     */
+    @Test
+    public void testBackGesture_max_scrimAtMinScale() {
+        mNotificationPanelViewController.onBackProgressed(1.0f);
+        verify(mScrimController).applyBackScaling(
+                NotificationPanelViewController.SHADE_BACK_ANIM_MIN_SCALE);
     }
 
     @Test
@@ -671,23 +149,6 @@
                 .isNotEqualTo(-1);
     }
 
-    private void setBottomPadding(int stackBottom, int lockIconPadding, int indicationPadding,
-            int ambientPadding) {
-
-        when(mNotificationStackScrollLayoutController.getTop()).thenReturn(0);
-        when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(stackBottom);
-        when(mNotificationStackScrollLayoutController.getBottom()).thenReturn(stackBottom);
-        when(mLockIconViewController.getTop()).thenReturn((float) (stackBottom - lockIconPadding));
-
-        when(mResources.getDimensionPixelSize(R.dimen.keyguard_indication_bottom_padding))
-                .thenReturn(indicationPadding);
-        mNotificationPanelViewController.loadDimens();
-
-        mNotificationPanelViewController.setAmbientIndicationTop(
-                /* ambientIndicationTop= */ stackBottom - ambientPadding,
-                /* ambientTextVisible= */ true);
-    }
-
     @Test
     @Ignore("b/261472011 - Test appears inconsistent across environments")
     public void getVerticalSpaceForLockscreenNotifications_useLockIconBottomPadding_returnsSpaceAvailable() {
@@ -992,68 +453,6 @@
     }
 
     @Test
-    public void testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() {
-        givenViewAttached();
-        when(mResources.getBoolean(
-                com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
-        updateMultiUserSetting(true);
-        clearInvocations(mView);
-
-        updateMultiUserSetting(false);
-
-        ArgumentCaptor<View> captor = ArgumentCaptor.forClass(View.class);
-        verify(mView, atLeastOnce()).addView(captor.capture(), anyInt());
-        final View userSwitcherStub = CollectionUtils.find(captor.getAllValues(),
-                view -> view.getId() == R.id.keyguard_user_switcher_stub);
-        assertThat(userSwitcherStub).isNotNull();
-        assertThat(userSwitcherStub).isInstanceOf(ViewStub.class);
-    }
-
-    @Test
-    public void testChangeSmallestScreenWidthAndUserSwitchEnabled_inflatesUserSwitchView() {
-        givenViewAttached();
-        when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(null);
-        updateSmallestScreenWidth(300);
-        when(mResources.getBoolean(
-                com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
-        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
-        when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true);
-
-        updateSmallestScreenWidth(800);
-
-        verify(mUserSwitcherStubView).inflate();
-    }
-
-    @Test
-    public void testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView_initClock() {
-        givenViewAttached();
-        when(mResources.getBoolean(
-                com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
-        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
-        when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
-                .thenReturn(false);
-
-        mNotificationPanelViewController.onFinishInflate();
-
-        verify(mUserSwitcherStubView, never()).inflate();
-        verify(mKeyguardStatusViewController, times(3)).displayClock(LARGE, /* animate */ true);
-    }
-
-    @Test
-    public void testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() {
-        givenViewAttached();
-        when(mResources.getBoolean(
-                com.android.internal.R.bool.config_keyguardUserSwitcher)).thenReturn(true);
-        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
-        when(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
-                .thenReturn(false);
-
-        mNotificationPanelViewController.reInflateViews();
-
-        verify(mUserSwitcherStubView, never()).inflate();
-    }
-
-    @Test
     public void testCanCollapsePanelOnTouch_trueForKeyGuard() {
         mStatusBarStateController.setState(KEYGUARD);
 
@@ -1129,26 +528,6 @@
     }
 
     @Test
-    public void testDoubleTapRequired_Keyguard() {
-        FalsingManager.FalsingTapListener listener = getFalsingTapListener();
-        mStatusBarStateController.setState(KEYGUARD);
-
-        listener.onAdditionalTapRequired();
-
-        verify(mKeyguardIndicationController).showTransientIndication(anyInt());
-    }
-
-    @Test
-    public void testDoubleTapRequired_ShadeLocked() {
-        FalsingManager.FalsingTapListener listener = getFalsingTapListener();
-        mStatusBarStateController.setState(SHADE_LOCKED);
-
-        listener.onAdditionalTapRequired();
-
-        verify(mTapAgainViewController).show();
-    }
-
-    @Test
     public void testRotatingToSplitShadeWithQsExpanded_transitionsToShadeLocked() {
         mStatusBarStateController.setState(KEYGUARD);
         when(mQsController.getExpanded()).thenReturn(true);
@@ -1423,19 +802,6 @@
     }
 
     @Test
-    public void testOnAttachRefreshStatusBarState() {
-        mStatusBarStateController.setState(KEYGUARD);
-        when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(false);
-        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
-            listener.onViewAttachedToWindow(mView);
-        }
-        verify(mKeyguardStatusViewController).setKeyguardStatusViewVisibility(
-                KEYGUARD/*statusBarState*/,
-                false/*keyguardFadingAway*/,
-                false/*goingToFullShade*/, SHADE/*oldStatusBarState*/);
-    }
-
-    @Test
     public void getMaxPanelTransitionDistance_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() {
         enableSplitShade(true);
         mNotificationPanelViewController.expandWithQs();
@@ -1635,98 +1001,4 @@
         mStatusBarStateController.setState(SHADE_LOCKED);
         assertThat(mNotificationPanelViewController.isShadeFullyOpen()).isTrue();
     }
-
-    private static MotionEvent createMotionEvent(int x, int y, int action) {
-        return MotionEvent.obtain(
-                /* downTime= */ 0, /* eventTime= */ 0, action, x, y, /* metaState= */ 0);
-    }
-
-    private void triggerPositionClockAndNotifications() {
-        mNotificationPanelViewController.onQsSetExpansionHeightCalled(false);
-    }
-
-    private FalsingManager.FalsingTapListener getFalsingTapListener() {
-        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
-            listener.onViewAttachedToWindow(mView);
-        }
-        assertThat(mFalsingManager.getTapListeners().size()).isEqualTo(1);
-        return mFalsingManager.getTapListeners().get(0);
-    }
-
-    private void givenViewAttached() {
-        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
-            listener.onViewAttachedToWindow(mView);
-        }
-    }
-
-    private ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
-        ConstraintSet constraintSet = new ConstraintSet();
-        constraintSet.clone(mNotificationContainerParent);
-        return constraintSet.getConstraint(id).layout;
-    }
-
-    private void enableSplitShade(boolean enabled) {
-        when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(enabled);
-        mNotificationPanelViewController.updateResources();
-    }
-
-    private void updateMultiUserSetting(boolean enabled) {
-        when(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user)).thenReturn(false);
-        when(mUserManager.isUserSwitcherEnabled(false)).thenReturn(enabled);
-        final ArgumentCaptor<ContentObserver> observerCaptor =
-                ArgumentCaptor.forClass(ContentObserver.class);
-        verify(mContentResolver)
-                .registerContentObserver(any(), anyBoolean(), observerCaptor.capture());
-        observerCaptor.getValue().onChange(/* selfChange */ false);
-    }
-
-    private void updateSmallestScreenWidth(int smallestScreenWidthDp) {
-        Configuration configuration = new Configuration();
-        configuration.smallestScreenWidthDp = smallestScreenWidthDp;
-        mConfigurationController.onConfigurationChanged(configuration);
-    }
-
-    private void onTouchEvent(MotionEvent ev) {
-        mTouchHandler.onTouch(mView, ev);
-    }
-
-    private void setDozing(boolean dozing, boolean dozingAlwaysOn) {
-        when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
-        mNotificationPanelViewController.setDozing(
-                /* dozing= */ dozing,
-                /* animate= */ false
-        );
-    }
-
-    private void assertKeyguardStatusViewCentered() {
-        mNotificationPanelViewController.updateResources();
-        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isAnyOf(
-                ConstraintSet.PARENT_ID, ConstraintSet.UNSET);
-    }
-
-    private void assertKeyguardStatusViewNotCentered() {
-        mNotificationPanelViewController.updateResources();
-        assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo(
-                R.id.qs_edge_guideline);
-    }
-
-    private void setIsFullWidth(boolean fullWidth) {
-        float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f;
-        when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth);
-        triggerLayoutChange();
-    }
-
-    private void triggerLayoutChange() {
-        mLayoutChangeListener.onLayoutChange(
-                mView,
-                /* left= */ 0,
-                /* top= */ 0,
-                /* right= */ 0,
-                /* bottom= */ 0,
-                /* oldLeft= */ 0,
-                /* oldTop= */ 0,
-                /* oldRight= */ 0,
-                /* oldBottom= */ 0
-        );
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
new file mode 100644
index 0000000..0c046e9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerWithCoroutinesTest.kt
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.shade
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import android.view.ViewStub
+import androidx.test.filters.SmallTest
+import com.android.internal.util.CollectionUtils
+import com.android.keyguard.KeyguardClockSwitch.LARGE
+import com.android.systemui.R
+import com.android.systemui.statusbar.StatusBarState.KEYGUARD
+import com.android.systemui.statusbar.StatusBarState.SHADE
+import com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
+import org.mockito.Mockito.atLeastOnce
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@SmallTest
+class NotificationPanelViewControllerWithCoroutinesTest :
+    NotificationPanelViewControllerBaseTest() {
+
+    @Captor private lateinit var viewCaptor: ArgumentCaptor<View>
+
+    override fun getMainDispatcher() = Dispatchers.Main.immediate
+
+    @Test
+    fun testDisableUserSwitcherAfterEnabling_returnsViewStubToTheViewHierarchy() = runTest {
+        launch(Dispatchers.Main.immediate) { givenViewAttached() }
+        advanceUntilIdle()
+
+        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+            .thenReturn(true)
+        updateMultiUserSetting(true)
+        clearInvocations(mView)
+
+        updateMultiUserSetting(false)
+
+        verify(mView, atLeastOnce()).addView(viewCaptor.capture(), anyInt())
+        val userSwitcherStub =
+            CollectionUtils.find(
+                viewCaptor.getAllValues(),
+                { view -> view.getId() == R.id.keyguard_user_switcher_stub }
+            )
+        assertThat(userSwitcherStub).isNotNull()
+        assertThat(userSwitcherStub).isInstanceOf(ViewStub::class.java)
+    }
+
+    @Test
+    fun testChangeSmallestScreenWidthAndUserSwitchEnabled_inflatesUserSwitchView() = runTest {
+        launch(Dispatchers.Main.immediate) { givenViewAttached() }
+        advanceUntilIdle()
+
+        whenever(mView.findViewById<View>(R.id.keyguard_user_switcher_view)).thenReturn(null)
+        updateSmallestScreenWidth(300)
+        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+            .thenReturn(true)
+        whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+            .thenReturn(false)
+        whenever(mUserManager.isUserSwitcherEnabled(false)).thenReturn(true)
+
+        updateSmallestScreenWidth(800)
+
+        verify(mUserSwitcherStubView).inflate()
+    }
+
+    @Test
+    fun testFinishInflate_userSwitcherDisabled_doNotInflateUserSwitchView_initClock() = runTest {
+        launch(Dispatchers.Main.immediate) { givenViewAttached() }
+        advanceUntilIdle()
+
+        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+            .thenReturn(true)
+        whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+            .thenReturn(false)
+        whenever(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+            .thenReturn(false)
+
+        mNotificationPanelViewController.onFinishInflate()
+
+        verify(mUserSwitcherStubView, never()).inflate()
+        verify(mKeyguardStatusViewController, times(3)).displayClock(LARGE, /* animate */ true)
+
+        coroutineContext.cancelChildren()
+    }
+
+    @Test
+    fun testReInflateViews_userSwitcherDisabled_doNotInflateUserSwitchView() = runTest {
+        launch(Dispatchers.Main.immediate) { givenViewAttached() }
+        advanceUntilIdle()
+
+        whenever(mResources.getBoolean(com.android.internal.R.bool.config_keyguardUserSwitcher))
+            .thenReturn(true)
+        whenever(mResources.getBoolean(R.bool.qs_show_user_switcher_for_single_user))
+            .thenReturn(false)
+        whenever(mUserManager.isUserSwitcherEnabled(false /* showEvenIfNotActionable */))
+            .thenReturn(false)
+
+        mNotificationPanelViewController.reInflateViews()
+
+        verify(mUserSwitcherStubView, never()).inflate()
+
+        coroutineContext.cancelChildren()
+    }
+
+    @Test
+    fun testDoubleTapRequired_Keyguard() = runTest {
+        launch(Dispatchers.Main.immediate) {
+            val listener = getFalsingTapListener()
+            mStatusBarStateController.setState(KEYGUARD)
+
+            listener.onAdditionalTapRequired()
+
+            verify(mKeyguardIndicationController).showTransientIndication(anyInt())
+        }
+        advanceUntilIdle()
+    }
+
+    @Test
+    fun testDoubleTapRequired_ShadeLocked() = runTest {
+        launch(Dispatchers.Main.immediate) {
+            val listener = getFalsingTapListener()
+            mStatusBarStateController.setState(SHADE_LOCKED)
+
+            listener.onAdditionalTapRequired()
+
+            verify(mTapAgainViewController).show()
+        }
+        advanceUntilIdle()
+    }
+
+    @Test
+    fun testOnAttachRefreshStatusBarState() = runTest {
+        launch(Dispatchers.Main.immediate) {
+            mStatusBarStateController.setState(KEYGUARD)
+            whenever(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(false)
+            mOnAttachStateChangeListeners.forEach { it.onViewAttachedToWindow(mView) }
+            verify(mKeyguardStatusViewController)
+                .setKeyguardStatusViewVisibility(
+                    KEYGUARD /*statusBarState*/,
+                    false /*keyguardFadingAway*/,
+                    false /*goingToFullShade*/,
+                    SHADE /*oldStatusBarState*/
+                )
+        }
+        advanceUntilIdle()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index d229a08..82a5743 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -28,11 +28,12 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.classifier.FalsingCollectorFake
 import com.android.systemui.dock.DockManager
-import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
 import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
 import com.android.systemui.statusbar.LockscreenShadeTransitionController
 import com.android.systemui.statusbar.NotificationInsetsController
@@ -47,6 +48,7 @@
 import com.android.systemui.statusbar.window.StatusBarWindowStateController
 import com.android.systemui.util.mockito.any
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.emptyFlow
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -64,50 +66,32 @@
 @RunWith(AndroidTestingRunner::class)
 @RunWithLooper(setAsMainLooper = true)
 class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
-    @Mock
-    private lateinit var view: NotificationShadeWindowView
-    @Mock
-    private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
-    @Mock
-    private lateinit var centralSurfaces: CentralSurfaces
-    @Mock
-    private lateinit var dockManager: DockManager
-    @Mock
-    private lateinit var notificationPanelViewController: NotificationPanelViewController
-    @Mock
-    private lateinit var notificationShadeDepthController: NotificationShadeDepthController
-    @Mock
-    private lateinit var notificationShadeWindowController: NotificationShadeWindowController
-    @Mock
-    private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
-    @Mock
-    private lateinit var featureFlags: FeatureFlags
-    @Mock
-    private lateinit var ambientState: AmbientState
-    @Mock
-    private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
-    @Mock
-    private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
-    @Mock
-    private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
-    @Mock
-    private lateinit var statusBarWindowStateController: StatusBarWindowStateController
+    @Mock private lateinit var view: NotificationShadeWindowView
+    @Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
+    @Mock private lateinit var centralSurfaces: CentralSurfaces
+    @Mock private lateinit var dockManager: DockManager
+    @Mock private lateinit var notificationPanelViewController: NotificationPanelViewController
+    @Mock private lateinit var notificationShadeDepthController: NotificationShadeDepthController
+    @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
+    @Mock private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
+    @Mock private lateinit var ambientState: AmbientState
+    @Mock private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
+    @Mock private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
+    @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+    @Mock private lateinit var statusBarWindowStateController: StatusBarWindowStateController
     @Mock
     private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
-    @Mock
-    private lateinit var lockIconViewController: LockIconViewController
-    @Mock
-    private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
-    @Mock
-    private lateinit var pulsingGestureListener: PulsingGestureListener
-    @Mock
-    private lateinit var notificationInsetsController: NotificationInsetsController
-    @Mock
-    private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
+    @Mock private lateinit var lockIconViewController: LockIconViewController
+    @Mock private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
+    @Mock private lateinit var pulsingGestureListener: PulsingGestureListener
+    @Mock private lateinit var notificationInsetsController: NotificationInsetsController
+    @Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
     @Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
     @Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
     @Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
     @Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
+    @Mock
+    lateinit var primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel
 
     private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
     private lateinit var interactionEventHandler: InteractionEventHandler
@@ -119,42 +103,44 @@
         MockitoAnnotations.initMocks(this)
         whenever(view.bottom).thenReturn(VIEW_BOTTOM)
         whenever(view.findViewById<ViewGroup>(R.id.keyguard_bouncer_container))
-                .thenReturn(mock(ViewGroup::class.java))
+            .thenReturn(mock(ViewGroup::class.java))
         whenever(keyguardBouncerComponentFactory.create(any(ViewGroup::class.java)))
-                .thenReturn(keyguardBouncerComponent)
+            .thenReturn(keyguardBouncerComponent)
         whenever(keyguardBouncerComponent.securityContainerController)
-                .thenReturn(keyguardSecurityContainerController)
-        underTest = NotificationShadeWindowViewController(
-            lockscreenShadeTransitionController,
-            FalsingCollectorFake(),
-            sysuiStatusBarStateController,
-            dockManager,
-            notificationShadeDepthController,
-            view,
-            notificationPanelViewController,
-            ShadeExpansionStateManager(),
-            stackScrollLayoutController,
-            statusBarKeyguardViewManager,
-            statusBarWindowStateController,
-            lockIconViewController,
-            centralSurfaces,
-            notificationShadeWindowController,
-            keyguardUnlockAnimationController,
-            notificationInsetsController,
-            ambientState,
-            pulsingGestureListener,
-            featureFlags,
-            keyguardBouncerViewModel,
-            keyguardBouncerComponentFactory,
-            alternateBouncerInteractor,
-            keyguardTransitionInteractor,
-        )
+            .thenReturn(keyguardSecurityContainerController)
+        whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
+            .thenReturn(emptyFlow<TransitionStep>())
+        underTest =
+            NotificationShadeWindowViewController(
+                lockscreenShadeTransitionController,
+                FalsingCollectorFake(),
+                sysuiStatusBarStateController,
+                dockManager,
+                notificationShadeDepthController,
+                view,
+                notificationPanelViewController,
+                ShadeExpansionStateManager(),
+                stackScrollLayoutController,
+                statusBarKeyguardViewManager,
+                statusBarWindowStateController,
+                lockIconViewController,
+                centralSurfaces,
+                notificationShadeWindowController,
+                keyguardUnlockAnimationController,
+                notificationInsetsController,
+                ambientState,
+                pulsingGestureListener,
+                keyguardBouncerViewModel,
+                keyguardBouncerComponentFactory,
+                alternateBouncerInteractor,
+                keyguardTransitionInteractor,
+                primaryBouncerToGoneTransitionViewModel,
+            )
         underTest.setupExpandedStatusBar()
 
-        interactionEventHandlerCaptor =
-            ArgumentCaptor.forClass(InteractionEventHandler::class.java)
+        interactionEventHandlerCaptor = ArgumentCaptor.forClass(InteractionEventHandler::class.java)
         verify(view).setInteractionEventHandler(interactionEventHandlerCaptor.capture())
-            interactionEventHandler = interactionEventHandlerCaptor.value
+        interactionEventHandler = interactionEventHandlerCaptor.value
     }
 
     // Note: So far, these tests only cover interactions with the status bar view controller. More
@@ -184,14 +170,11 @@
     @Test
     fun handleDispatchTouchEvent_downTouchBelowViewThenAnotherTouch_sendsTouchToSb() {
         underTest.setStatusBarViewController(phoneStatusBarViewController)
-        val downEvBelow = MotionEvent.obtain(
-            0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0
-        )
+        val downEvBelow =
+            MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0)
         interactionEventHandler.handleDispatchTouchEvent(downEvBelow)
 
-        val nextEvent = MotionEvent.obtain(
-            0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0
-        )
+        val nextEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0)
         whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true)
 
         val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
index 5e9c219..faa6221 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewTest.java
@@ -25,6 +25,8 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
 import android.os.SystemClock;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -40,11 +42,11 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.dock.DockManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
+import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.NotificationInsetsController;
@@ -93,7 +95,6 @@
     @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
     @Mock private AmbientState mAmbientState;
     @Mock private PulsingGestureListener mPulsingGestureListener;
-    @Mock private FeatureFlags mFeatureFlags;
     @Mock private KeyguardBouncerViewModel mKeyguardBouncerViewModel;
     @Mock private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory;
     @Mock private KeyguardBouncerComponent mKeyguardBouncerComponent;
@@ -101,6 +102,7 @@
     @Mock private NotificationInsetsController mNotificationInsetsController;
     @Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
     @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+    @Mock private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
 
     @Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
             mInteractionEventHandlerCaptor;
@@ -125,6 +127,9 @@
 
         when(mDockManager.isDocked()).thenReturn(false);
 
+        when(mKeyguardTransitionInteractor.getLockscreenToDreamingTransition())
+                .thenReturn(emptyFlow());
+
         mController = new NotificationShadeWindowViewController(
                 mLockscreenShadeTransitionController,
                 new FalsingCollectorFake(),
@@ -144,11 +149,11 @@
                 mNotificationInsetsController,
                 mAmbientState,
                 mPulsingGestureListener,
-                mFeatureFlags,
                 mKeyguardBouncerViewModel,
                 mKeyguardBouncerComponentFactory,
                 mAlternateBouncerInteractor,
-                mKeyguardTransitionInteractor
+                mKeyguardTransitionInteractor,
+                mPrimaryBouncerToGoneTransitionViewModel
         );
         mController.setupExpandedStatusBar();
         mController.setDragDownHelper(mDragDownHelper);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
index 7a74b12..56fc0c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
@@ -36,21 +36,26 @@
 
     private val progressProvider = TestUnfoldTransitionProvider()
 
-    @Mock private lateinit var parent: ViewGroup
+    @Mock
+    private lateinit var parent: ViewGroup
+
+    @Mock
+    private lateinit var shouldBeAnimated: () -> Boolean
 
     private lateinit var animator: UnfoldConstantTranslateAnimator
 
-    private val viewsIdToRegister =
-        setOf(
-            ViewIdToTranslate(START_VIEW_ID, Direction.START),
-            ViewIdToTranslate(END_VIEW_ID, Direction.END))
+    private val viewsIdToRegister
+        get() =
+            setOf(
+                    ViewIdToTranslate(START_VIEW_ID, Direction.START, shouldBeAnimated),
+                    ViewIdToTranslate(END_VIEW_ID, Direction.END, shouldBeAnimated)
+            )
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-
-        animator =
-            UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
+        whenever(shouldBeAnimated.invoke()).thenReturn(true)
+        animator = UnfoldConstantTranslateAnimator(viewsIdToRegister, progressProvider)
 
         animator.init(parent, MAX_TRANSLATION)
     }
@@ -96,6 +101,20 @@
         moveAndValidate(listOf(leftView to START, rightView to END), View.LAYOUT_DIRECTION_LTR)
     }
 
+    @Test
+    fun onTransition_completeStartedTranslation() {
+        // GIVEN
+        val leftView = View(context)
+        whenever(parent.findViewById<View>(START_VIEW_ID)).thenReturn(leftView)
+        // To start animation, shouldBeAnimated should return true.
+        // There is a possibility for shouldBeAnimated to return false during the animation.
+        whenever(shouldBeAnimated.invoke()).thenReturn(true).thenReturn(false)
+
+        // shouldBeAnimated state may change during the animation.
+        // However, started animation should be completed.
+        moveAndValidate(listOf(leftView to START), View.LAYOUT_DIRECTION_LTR)
+    }
+
     private fun moveAndValidate(list: List<Pair<View, Int>>, layoutDirection: Int) {
         // Compare values as ints because -0f != 0f
 
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 26eff61..1fdb364 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
@@ -35,7 +35,6 @@
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
-import org.json.JSONException
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -271,10 +270,14 @@
 
     @Test
     fun jsonDeserialization_gotExpectedObject() {
-        val expected = ClockSettings("ID", null).apply { _applied_timestamp = 500 }
+        val expected = ClockSettings("ID", null).apply {
+            metadata.put("appliedTimestamp", 500)
+        }
         val actual = ClockSettings.deserialize("""{
             "clockId":"ID",
-            "_applied_timestamp":500
+            "metadata": {
+                "appliedTimestamp":500
+            }
         }""")
         assertEquals(expected, actual)
     }
@@ -291,29 +294,32 @@
         val expected = ClockSettings("ID", null)
         val actual = ClockSettings.deserialize("""{
             "clockId":"ID",
-            "_applied_timestamp":null
+            "metadata":null
         }""")
         assertEquals(expected, actual)
     }
 
-    @Test(expected = JSONException::class)
-    fun jsonDeserialization_noId_threwException() {
-        val expected = ClockSettings(null, null).apply { _applied_timestamp = 500 }
-        val actual = ClockSettings.deserialize("{\"_applied_timestamp\":500}")
+    @Test
+    fun jsonDeserialization_noId_deserializedEmpty() {
+        val expected = ClockSettings(null, null).apply {
+            metadata.put("appliedTimestamp", 500)
+        }
+        val actual = ClockSettings.deserialize("{\"metadata\":{\"appliedTimestamp\":500}}")
         assertEquals(expected, actual)
     }
 
     @Test
     fun jsonSerialization_gotExpectedString() {
-        val expected = "{\"clockId\":\"ID\",\"_applied_timestamp\":500}"
-        val actual = ClockSettings.serialize(ClockSettings("ID", null)
-            .apply { _applied_timestamp = 500 })
+        val expected = "{\"clockId\":\"ID\",\"metadata\":{\"appliedTimestamp\":500}}"
+        val actual = ClockSettings.serialize(ClockSettings("ID", null).apply {
+            metadata.put("appliedTimestamp", 500)
+        })
         assertEquals(expected, actual)
     }
 
     @Test
     fun jsonSerialization_noTimestamp_gotExpectedString() {
-        val expected = "{\"clockId\":\"ID\"}"
+        val expected = "{\"clockId\":\"ID\",\"metadata\":{}}"
         val actual = ClockSettings.serialize(ClockSettings("ID", 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 cd2efc0..7fa27f3 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
@@ -26,6 +26,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.ClockSettings
 import com.android.systemui.shared.clocks.DefaultClockController.Companion.DOZE_COLOR
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
@@ -40,7 +41,6 @@
 import org.junit.runner.RunWith
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.ArgumentMatchers.anyFloat
-import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.notNull
 import org.mockito.Mock
 import org.mockito.Mockito.never
@@ -97,13 +97,14 @@
     @Test
     fun defaultClock_initialize() {
         val clock = provider.createClock(DEFAULT_CLOCK_ID)
-        verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
-        verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
+        verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
 
         clock.initialize(resources, 0f, 0f)
 
-        verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
-        verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
+        val expectedColor = 0
+        verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
         verify(mockSmallClockView).onTimeZoneChanged(notNull())
         verify(mockLargeClockView).onTimeZoneChanged(notNull())
         verify(mockSmallClockView).refreshTime()
@@ -159,15 +160,31 @@
 
     @Test
     fun defaultClock_events_onColorPaletteChanged() {
+        val expectedColor = 0
         val clock = provider.createClock(DEFAULT_CLOCK_ID)
 
-        verify(mockSmallClockView).setColors(Color.MAGENTA, Color.MAGENTA)
-        verify(mockLargeClockView).setColors(Color.MAGENTA, Color.MAGENTA)
+        verify(mockSmallClockView).setColors(DOZE_COLOR, Color.MAGENTA)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, Color.MAGENTA)
 
         clock.events.onColorPaletteChanged(resources)
 
-        verify(mockSmallClockView).setColors(eq(DOZE_COLOR), anyInt())
-        verify(mockLargeClockView).setColors(eq(DOZE_COLOR), anyInt())
+        verify(mockSmallClockView).setColors(DOZE_COLOR, expectedColor)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, expectedColor)
+    }
+
+    @Test
+    fun defaultClock_events_onSeedColorChanged() {
+        val initSeedColor = 10
+        val newSeedColor = 20
+        val clock = provider.createClock(ClockSettings(DEFAULT_CLOCK_ID, initSeedColor))
+
+        verify(mockSmallClockView).setColors(DOZE_COLOR, initSeedColor)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, initSeedColor)
+
+        clock.events.onSeedColorChanged(newSeedColor)
+
+        verify(mockSmallClockView).setColors(DOZE_COLOR, newSeedColor)
+        verify(mockLargeClockView).setColors(DOZE_COLOR, newSeedColor)
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java
index bea2cfb..bedb2b3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyboardShortcutsReceiverTest.java
@@ -73,7 +73,7 @@
                 .startMocking();
         mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
         mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
-        when(Utilities.isTablet(mContext)).thenReturn(true);
+        when(Utilities.isLargeScreen(mContext)).thenReturn(true);
 
         mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
 
@@ -90,7 +90,7 @@
                 .startMocking();
         mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
         mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
-        when(Utilities.isTablet(mContext)).thenReturn(false);
+        when(Utilities.isLargeScreen(mContext)).thenReturn(false);
 
         mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
 
@@ -107,7 +107,7 @@
                 .startMocking();
         mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, true);
         mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
-        when(Utilities.isTablet(mContext)).thenReturn(true);
+        when(Utilities.isLargeScreen(mContext)).thenReturn(true);
 
         mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
 
@@ -124,7 +124,7 @@
                 .startMocking();
         mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, true);
         mKeyboardShortcutsReceiver = spy(new KeyboardShortcutsReceiver(mFeatureFlags));
-        when(Utilities.isTablet(mContext)).thenReturn(false);
+        when(Utilities.isLargeScreen(mContext)).thenReturn(false);
 
         mKeyboardShortcutsReceiver.onReceive(mContext, mIntent);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index d99cdd51..ab615f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -211,16 +211,6 @@
     }
 
     @Test
-    fun testTriggeringBouncerWhenPrivateNotificationsArentAllowed() {
-        whenever(lockScreenUserManager.userAllowsPrivateNotificationsInPublic(anyInt())).thenReturn(
-                false)
-        transitionController.goToLockedShade(null)
-        verify(statusbarStateController, never()).setState(anyInt())
-        verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
-        verify(mCentralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
-    }
-
-    @Test
     fun testTriggeringBouncerNoNotificationsOnLockscreen() {
         whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
         transitionController.goToLockedShade(null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
new file mode 100644
index 0000000..7a67796
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.statusbar.StatusBarState
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationWakeUpCoordinatorLoggerTest : SysuiTestCase() {
+
+    private val logBufferCounter = LogBufferCounter()
+    private lateinit var logger: NotificationWakeUpCoordinatorLogger
+
+    private fun verifyDidLog(times: Int) {
+        logBufferCounter.verifyDidLog(times)
+    }
+
+    @Before
+    fun setup() {
+        logger = NotificationWakeUpCoordinatorLogger(logBufferCounter.logBuffer)
+    }
+
+    @Test
+    fun setDozeAmountWillThrottleFractionalUpdates() {
+        logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(0)
+        logger.logSetDozeAmount(1f, 1f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(1)
+    }
+
+    @Test
+    fun setDozeAmountWillIncludeFractionalUpdatesWhenStateChanges() {
+        logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(0)
+        logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.KEYGUARD, changed = false)
+        verifyDidLog(1)
+    }
+
+    @Test
+    fun setDozeAmountWillIncludeFractionalUpdatesWhenSourceChanges() {
+        logger.logSetDozeAmount(0f, 0f, "source1", StatusBarState.SHADE, changed = false)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.1f, 0.1f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(1)
+        logger.logSetDozeAmount(0.2f, 0.2f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.3f, 0.3f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.4f, 0.4f, "source1", StatusBarState.SHADE, changed = true)
+        logger.logSetDozeAmount(0.5f, 0.5f, "source1", StatusBarState.SHADE, changed = true)
+        verifyDidLog(0)
+        logger.logSetDozeAmount(0.5f, 0.5f, "source2", StatusBarState.SHADE, changed = false)
+        verifyDidLog(1)
+    }
+
+    class LogBufferCounter {
+        val recentLogs = mutableListOf<Pair<String, LogLevel>>()
+        val tracker =
+            object : LogcatEchoTracker {
+                override val logInBackgroundThread: Boolean = false
+                override fun isBufferLoggable(bufferName: String, level: LogLevel): Boolean = false
+                override fun isTagLoggable(tagName: String, level: LogLevel): Boolean {
+                    recentLogs.add(tagName to level)
+                    return true
+                }
+            }
+        val logBuffer =
+            LogBuffer(name = "test", maxSize = 1, logcatEchoTracker = tracker, systrace = false)
+
+        fun verifyDidLog(times: Int) {
+            assertThat(recentLogs).hasSize(times)
+            recentLogs.clear()
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
new file mode 100644
index 0000000..95591a4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorTest.kt
@@ -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 com.android.systemui.statusbar.notification
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.statusbar.policy.HeadsUpManager
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.anyFloat
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.verify
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NotificationWakeUpCoordinatorTest : SysuiTestCase() {
+
+    private val dumpManager: DumpManager = mock()
+    private val headsUpManager: HeadsUpManager = mock()
+    private val statusBarStateController: StatusBarStateController = mock()
+    private val bypassController: KeyguardBypassController = mock()
+    private val dozeParameters: DozeParameters = mock()
+    private val screenOffAnimationController: ScreenOffAnimationController = mock()
+    private val logger: NotificationWakeUpCoordinatorLogger = mock()
+    private val stackScrollerController: NotificationStackScrollLayoutController = mock()
+
+    private lateinit var notificationWakeUpCoordinator: NotificationWakeUpCoordinator
+    private lateinit var statusBarStateCallback: StatusBarStateController.StateListener
+    private lateinit var bypassChangeCallback: KeyguardBypassController.OnBypassStateChangedListener
+
+    private var bypassEnabled: Boolean = false
+    private var statusBarState: Int = StatusBarState.KEYGUARD
+    private var dozeAmount: Float = 0f
+
+    private fun setBypassEnabled(enabled: Boolean) {
+        bypassEnabled = enabled
+        bypassChangeCallback.onBypassStateChanged(enabled)
+    }
+
+    private fun setStatusBarState(state: Int) {
+        statusBarState = state
+        statusBarStateCallback.onStateChanged(state)
+    }
+
+    private fun setDozeAmount(dozeAmount: Float) {
+        this.dozeAmount = dozeAmount
+        statusBarStateCallback.onDozeAmountChanged(dozeAmount, dozeAmount)
+    }
+
+    @Before
+    fun setup() {
+        whenever(bypassController.bypassEnabled).then { bypassEnabled }
+        whenever(statusBarStateController.state).then { statusBarState }
+        notificationWakeUpCoordinator =
+            NotificationWakeUpCoordinator(
+                dumpManager,
+                headsUpManager,
+                statusBarStateController,
+                bypassController,
+                dozeParameters,
+                screenOffAnimationController,
+                logger,
+            )
+        statusBarStateCallback = withArgCaptor {
+            verify(statusBarStateController).addCallback(capture())
+        }
+        bypassChangeCallback = withArgCaptor {
+            verify(bypassController).registerOnBypassStateChangedListener(capture())
+        }
+        notificationWakeUpCoordinator.setStackScroller(stackScrollerController)
+    }
+
+    @Test
+    fun setDozeToOneWillFullyHideNotifications() {
+        setDozeAmount(1f)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 1f, hideAmount = 1f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
+    }
+
+    @Test
+    fun setDozeToZeroWillFullyShowNotifications() {
+        setDozeAmount(0f)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+    }
+
+    @Test
+    fun setDozeToOneThenZeroWillFullyShowNotifications() {
+        setDozeToOneWillFullyHideNotifications()
+        clearInvocations(stackScrollerController)
+        setDozeToZeroWillFullyShowNotifications()
+    }
+
+    @Test
+    fun setDozeToHalfWillHalfShowNotifications() {
+        setDozeAmount(0.5f)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0.5f, hideAmount = 0.5f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+    }
+
+    @Test
+    fun setDozeToZeroWithBypassWillFullyHideNotifications() {
+        bypassEnabled = true
+        setDozeAmount(0f)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 01f, hideAmount = 1f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isTrue()
+    }
+
+    @Test
+    fun disablingBypassWillShowNotifications() {
+        setDozeToZeroWithBypassWillFullyHideNotifications()
+        clearInvocations(stackScrollerController)
+        setBypassEnabled(false)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+    }
+
+    @Test
+    fun switchingToShadeWithBypassEnabledWillShowNotifications() {
+        setDozeToZeroWithBypassWillFullyHideNotifications()
+        clearInvocations(stackScrollerController)
+        setStatusBarState(StatusBarState.SHADE)
+        verifyStackScrollerDozeAndHideAmount(dozeAmount = 0f, hideAmount = 0f)
+        assertThat(notificationWakeUpCoordinator.notificationsFullyHidden).isFalse()
+        assertThat(notificationWakeUpCoordinator.statusBarState).isEqualTo(StatusBarState.SHADE)
+    }
+
+    private fun verifyStackScrollerDozeAndHideAmount(dozeAmount: Float, hideAmount: Float) {
+        // First verify that we did in-fact receive the correct values
+        verify(stackScrollerController).setDozeAmount(dozeAmount)
+        verify(stackScrollerController).setHideAmount(hideAmount, hideAmount)
+        // Now verify that there was just this ONE call to each of these methods
+        verify(stackScrollerController).setDozeAmount(anyFloat())
+        verify(stackScrollerController).setHideAmount(anyFloat(), anyFloat())
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt
deleted file mode 100644
index a6a9e51..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeRepoTest.kt
+++ /dev/null
@@ -1,210 +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.statusbar.notification.fsi
-
-import android.R
-import android.app.Notification
-import android.app.NotificationManager
-import android.app.PendingIntent
-import android.content.pm.ApplicationInfo
-import android.content.pm.PackageManager
-import android.graphics.drawable.Drawable
-import android.os.UserHandle
-import android.service.dreams.IDreamManager
-import android.service.notification.StatusBarNotification
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-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.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.provider.LaunchFullScreenIntentProvider
-import com.android.systemui.statusbar.phone.CentralSurfaces
-import java.util.concurrent.Executor
-import junit.framework.Assert.assertEquals
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyString
-import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.never
-import org.mockito.Mockito.times
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper(setAsMainLooper = true)
-class FsiChromeRepoTest : SysuiTestCase() {
-
-    @Mock lateinit var centralSurfaces: CentralSurfaces
-    @Mock lateinit var fsiChromeRepo: FsiChromeRepo
-    @Mock lateinit var packageManager: PackageManager
-
-    var keyguardRepo = FakeKeyguardRepository()
-    @Mock private lateinit var applicationInfo: ApplicationInfo
-
-    @Mock lateinit var launchFullScreenIntentProvider: LaunchFullScreenIntentProvider
-    var featureFlags = FakeFeatureFlags()
-    @Mock lateinit var dreamManager: IDreamManager
-
-    // Execute all foreground & background requests immediately
-    private val uiBgExecutor = Executor { r -> r.run() }
-
-    private val appName: String = "appName"
-    private val appIcon: Drawable = context.getDrawable(com.android.systemui.R.drawable.ic_android)
-    private val fsi: PendingIntent = Mockito.mock(PendingIntent::class.java)
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        // Set up package manager mocks
-        whenever(packageManager.getApplicationIcon(anyString())).thenReturn(appIcon)
-        whenever(packageManager.getApplicationIcon(any(ApplicationInfo::class.java)))
-            .thenReturn(appIcon)
-        whenever(packageManager.getApplicationLabel(any())).thenReturn(appName)
-        mContext.setMockPackageManager(packageManager)
-
-        fsiChromeRepo =
-            FsiChromeRepo(
-                mContext,
-                packageManager,
-                keyguardRepo,
-                launchFullScreenIntentProvider,
-                featureFlags,
-                uiBgExecutor,
-                dreamManager,
-                centralSurfaces
-            )
-    }
-
-    private fun createFsiEntry(fsi: PendingIntent): NotificationEntry {
-        val nb =
-            Notification.Builder(mContext, "a")
-                .setContentTitle("foo")
-                .setSmallIcon(R.drawable.sym_def_app_icon)
-                .setFullScreenIntent(fsi, /* highPriority= */ true)
-
-        val sbn =
-            StatusBarNotification(
-                "pkg",
-                "opPkg",
-                /* id= */ 0,
-                "tag" + System.currentTimeMillis(),
-                /* uid= */ 0,
-                /* initialPid */ 0,
-                nb.build(),
-                UserHandle(0),
-                /* overrideGroupKey= */ null,
-                /* postTime= */ 0
-            )
-
-        val entry = Mockito.mock(NotificationEntry::class.java)
-        whenever(entry.importance).thenReturn(NotificationManager.IMPORTANCE_HIGH)
-        whenever(entry.sbn).thenReturn(sbn)
-        return entry
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_flagNotEnabled_noLaunch() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, false)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(centralSurfaces, never()).wakeUpForFullScreenIntent()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_notOnKeyguard_noLaunch() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(false)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(centralSurfaces, never()).wakeUpForFullScreenIntent()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_stopsScreensaver() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(dreamManager, times(1)).awaken()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_updatesFsiInfoFlow() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        val expectedFsiInfo = FsiChromeRepo.FSIInfo(appName, appIcon, fsi)
-        assertEquals(expectedFsiInfo, fsiChromeRepo.infoFlow.value)
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_notifyFsiLaunched() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(entry, times(1)).notifyFullScreenIntentLaunched()
-    }
-
-    @Test
-    fun testLaunchFullscreenIntent_wakesUpDevice() {
-        // Setup
-        featureFlags.set(Flags.FSI_CHROME, true)
-        keyguardRepo.setKeyguardShowing(true)
-
-        // Test
-        val entry = createFsiEntry(fsi)
-        fsiChromeRepo.launchFullscreenIntent(entry)
-
-        // Verify
-        Mockito.verify(centralSurfaces, times(1)).wakeUpForFullScreenIntent()
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt
deleted file mode 100644
index 5cee9e3..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/fsi/FsiChromeViewModelFactoryTest.kt
+++ /dev/null
@@ -1,112 +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.statusbar.notification.fsi
-
-import android.app.PendingIntent
-import android.graphics.drawable.Drawable
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dagger.qualifiers.Main
-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.mockito.whenever
-import com.android.systemui.util.mockito.withArgCaptor
-import com.android.systemui.util.time.FakeSystemClock
-import com.android.wm.shell.TaskView
-import com.android.wm.shell.TaskViewFactory
-import com.google.common.truth.Truth.assertThat
-import java.util.Optional
-import java.util.function.Consumer
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.flow.stateIn
-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.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper(setAsMainLooper = true)
-class FsiChromeViewModelFactoryTest : SysuiTestCase() {
-    @Mock private lateinit var taskViewFactoryOptional: Optional<TaskViewFactory>
-    @Mock private lateinit var taskViewFactory: TaskViewFactory
-    @Mock lateinit var taskView: TaskView
-
-    @Main var mainExecutor = FakeExecutor(FakeSystemClock())
-    lateinit var viewModelFactory: FsiChromeViewModelFactory
-
-    private val fakeInfoFlow = MutableStateFlow<FsiChromeRepo.FSIInfo?>(null)
-    private var fsiChromeRepo: FsiChromeRepo =
-        mock<FsiChromeRepo>().apply { whenever(infoFlow).thenReturn(fakeInfoFlow) }
-
-    private val appName = "appName"
-    private val appIcon: Drawable = context.getDrawable(com.android.systemui.R.drawable.ic_android)
-    private val fsi: PendingIntent = Mockito.mock(PendingIntent::class.java)
-    private val fsiInfo = FsiChromeRepo.FSIInfo(appName, appIcon, fsi)
-
-    @Before
-    fun setUp() {
-        MockitoAnnotations.initMocks(this)
-
-        whenever(taskViewFactoryOptional.get()).thenReturn(taskViewFactory)
-
-        viewModelFactory =
-            FsiChromeViewModelFactory(fsiChromeRepo, taskViewFactoryOptional, context, mainExecutor)
-    }
-
-    @Test
-    fun testViewModelFlow_update_createsTaskView() {
-        runTest {
-            val latestViewModel =
-                viewModelFactory.viewModelFlow
-                    .onStart { FsiDebug.log("viewModelFactory.viewModelFlow.onStart") }
-                    .stateIn(
-                        backgroundScope, // stateIn runs forever, don't count it as test coroutine
-                        SharingStarted.Eagerly,
-                        null
-                    )
-            runCurrent() // Drain queued backgroundScope operations
-
-            // Test: emit the fake FSIInfo
-            fakeInfoFlow.emit(fsiInfo)
-            runCurrent()
-
-            val taskViewFactoryCallback: Consumer<TaskView> = withArgCaptor {
-                verify(taskViewFactory).create(any(), any(), capture())
-            }
-            taskViewFactoryCallback.accept(taskView) // this will call k.resume
-            runCurrent()
-
-            // Verify that the factory has produced a new ViewModel
-            // containing the relevant data from FsiInfo
-            val expectedViewModel =
-                FsiChromeViewModel(appName, appIcon, taskView, fsi, fsiChromeRepo)
-
-            assertThat(latestViewModel.value).isEqualTo(expectedViewModel)
-        }
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 5b8305d..89c399b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -415,6 +415,37 @@
         verify(mNotificationStackScrollLayout).updateEmptyShadeView(anyBoolean(), anyBoolean());
     }
 
+    @Test
+    public void testAttach_updatesViewStatusBarState() {
+        // GIVEN: Controller is attached
+        mController.attach(mNotificationStackScrollLayout);
+        ArgumentCaptor<StatusBarStateController.StateListener> captor =
+                ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
+        verify(mSysuiStatusBarStateController).addCallback(captor.capture(), anyInt());
+        StatusBarStateController.StateListener stateListener = captor.getValue();
+
+        // WHEN: StatusBarState changes to SHADE
+        when(mSysuiStatusBarStateController.getState()).thenReturn(SHADE);
+        stateListener.onStateChanged(SHADE);
+
+        // THEN: NSSL is updated with the current state
+        verify(mNotificationStackScrollLayout).setStatusBarState(SHADE);
+
+        // WHEN: Controller is detached
+        mController.mOnAttachStateChangeListener
+                .onViewDetachedFromWindow(mNotificationStackScrollLayout);
+
+        // WHEN: StatusBarState changes to KEYGUARD
+        when(mSysuiStatusBarStateController.getState()).thenReturn(KEYGUARD);
+
+        // WHEN: Controller is re-attached
+        mController.mOnAttachStateChangeListener
+                .onViewAttachedToWindow(mNotificationStackScrollLayout);
+
+        // THEN: NSSL is updated with the current state
+        verify(mNotificationStackScrollLayout).setStatusBarState(KEYGUARD);
+    }
+
     private LogMaker logMatcher(int category, int type) {
         return argThat(new LogMatcher(category, type));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 680a323..78da782 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -20,6 +20,7 @@
 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.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -227,14 +228,154 @@
     }
 
     @Test
-    public void testHandleUpEvent_menuRow() {
-        when(mSwipeHelper.getCurrentMenuRow()).thenReturn(mMenuRow);
-        doNothing().when(mSwipeHelper).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+    public void testHandleUpEvent_menuRowWithoutMenu_dismiss() {
+        doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+        doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
 
         assertTrue("Menu row exists",
                 mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
         verify(mMenuRow, times(1)).onTouchEnd();
-        verify(mSwipeHelper, times(1)).handleMenuRowSwipe(mEvent, mView, 0, mMenuRow);
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRowWithoutMenu_snapback() {
+        doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+        doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+        verify(mMenuRow, times(1)).onSnapClosed();
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRowWithOpenMenu_dismissed() {
+        doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+        doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(true);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRowWithOpenMenu_snapback() {
+        doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+        doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(true);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+        verify(mMenuRow, times(1)).onSnapClosed();
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRowWithClosedMenu_dismissed() {
+        doNothing().when(mSwipeHelper).dismiss(any(), anyFloat());
+        doReturn(true).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(false);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).dismiss(mView, 0);
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testHandleUpEvent_menuRowWithClosedMenu_snapback() {
+        doNothing().when(mSwipeHelper).snapChild(any(), anyInt(), anyFloat());
+        doReturn(false).when(mSwipeHelper).isDismissGesture(any());
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        when(mMenuRow.shouldShowMenu()).thenReturn(true);
+        when(mMenuRow.isSnappedAndOnSameSide()).thenReturn(false);
+        mSwipeHelper.setCurrentMenuRow(mMenuRow);
+
+        assertTrue("Menu row exists",
+                mSwipeHelper.handleUpEvent(mEvent, mView, 0, 0));
+        verify(mMenuRow, times(1)).onTouchEnd();
+        verify(mSwipeHelper, times(1)).isDismissGesture(mEvent);
+        verify(mSwipeHelper, times(1)).snapClosed(mView, 0);
+        verify(mMenuRow, times(1)).onSnapClosed();
+        verify(mSwipeHelper, never()).isFalseGesture();
+    }
+
+    @Test
+    public void testIsDismissGesture() {
+        doReturn(false).when(mSwipeHelper).isFalseGesture();
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        doReturn(true).when(mSwipeHelper).swipedFastEnough();
+        when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+        when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+        assertTrue("Should be a dismiss gesture", mSwipeHelper.isDismissGesture(mEvent));
+        verify(mSwipeHelper, times(1)).isFalseGesture();
+    }
+
+    @Test
+    public void testIsDismissGesture_falseGesture() {
+        doReturn(true).when(mSwipeHelper).isFalseGesture();
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        doReturn(true).when(mSwipeHelper).swipedFastEnough();
+        when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+        when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+        assertFalse("False gesture should stop dismissal", mSwipeHelper.isDismissGesture(mEvent));
+        verify(mSwipeHelper, times(1)).isFalseGesture();
+    }
+
+    @Test
+    public void testIsDismissGesture_farEnough() {
+        doReturn(false).when(mSwipeHelper).isFalseGesture();
+        doReturn(true).when(mSwipeHelper).swipedFarEnough();
+        doReturn(false).when(mSwipeHelper).swipedFastEnough();
+        when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+        when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+        assertTrue("Should be a dismissal", mSwipeHelper.isDismissGesture(mEvent));
+        verify(mSwipeHelper, times(1)).isFalseGesture();
+    }
+
+    @Test
+    public void testIsDismissGesture_notFarOrFastEnough() {
+        doReturn(false).when(mSwipeHelper).isFalseGesture();
+        doReturn(false).when(mSwipeHelper).swipedFarEnough();
+        doReturn(false).when(mSwipeHelper).swipedFastEnough();
+        when(mCallback.canChildBeDismissedInDirection(any(), anyBoolean())).thenReturn(true);
+        when(mEvent.getActionMasked()).thenReturn(MotionEvent.ACTION_UP);
+
+        assertFalse("Should not be a dismissal", mSwipeHelper.isDismissGesture(mEvent));
+        verify(mSwipeHelper, times(1)).isFalseGesture();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index ec294b1..68d67ca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -517,6 +517,26 @@
         verify(mVibratorHelper).vibrateAuthError(anyString());
     }
 
+    @Test
+    public void onFingerprintDetect_showBouncer() {
+        // WHEN fingerprint detect occurs
+        mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
+                BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);
+
+        // THEN shows primary bouncer
+        verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
+    }
+
+    @Test
+    public void onFaceDetect_showBouncer() {
+        // WHEN face detect occurs
+        mBiometricUnlockController.onBiometricDetected(UserHandle.USER_CURRENT,
+                BiometricSourceType.FACE, false /* isStrongBiometric */);
+
+        // THEN shows primary bouncer
+        verify(mStatusBarKeyguardViewManager).showPrimaryBouncer(anyBoolean());
+    }
+
     private void givenFingerprintModeUnlockCollapsing() {
         when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
         when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 38e8228..c4ee326 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -77,6 +77,8 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewRootImpl;
 import android.view.WindowManager;
+import android.window.BackEvent;
+import android.window.OnBackAnimationCallback;
 import android.window.OnBackInvokedCallback;
 import android.window.OnBackInvokedDispatcher;
 import android.window.WindowOnBackInvokedDispatcher;
@@ -114,6 +116,7 @@
 import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
 import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel;
 import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.notetask.NoteTaskController;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.plugins.PluginManager;
@@ -181,6 +184,8 @@
 import com.android.wm.shell.bubbles.Bubbles;
 import com.android.wm.shell.startingsurface.StartingSurface;
 
+import dagger.Lazy;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -193,8 +198,6 @@
 import java.io.PrintWriter;
 import java.util.Optional;
 
-import dagger.Lazy;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
@@ -259,6 +262,7 @@
     @Mock private StatusBarWindowStateController mStatusBarWindowStateController;
     @Mock private UserSwitcherController mUserSwitcherController;
     @Mock private Bubbles mBubbles;
+    @Mock private NoteTaskController mNoteTaskController;
     @Mock private NotificationShadeWindowController mNotificationShadeWindowController;
     @Mock private NotificationIconAreaController mNotificationIconAreaController;
     @Mock private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
@@ -331,6 +335,10 @@
         mFeatureFlags.set(Flags.WM_ENABLE_PREDICTIVE_BACK_SYSUI, false);
         // Set default value to avoid IllegalStateException.
         mFeatureFlags.set(Flags.SHORTCUT_LIST_SEARCH_LAYOUT, false);
+        // For the Shade to respond to Back gesture, we must enable the event routing
+        mFeatureFlags.set(Flags.WM_SHADE_ALLOW_BACK_GESTURE, true);
+        // For the Shade to animate during the Back gesture, we must enable the animation flag.
+        mFeatureFlags.set(Flags.WM_SHADE_ANIMATE_BACK_GESTURE, true);
 
         IThermalService thermalService = mock(IThermalService.class);
         mPowerManager = new PowerManager(mContext, mPowerManagerService, thermalService,
@@ -472,6 +480,7 @@
                 mWakefulnessLifecycle,
                 mStatusBarStateController,
                 Optional.of(mBubbles),
+                () -> mNoteTaskController,
                 mDeviceProvisionedController,
                 mNavigationBarController,
                 mAccessibilityFloatingMenuController,
@@ -852,6 +861,50 @@
         verify(mShadeController).animateCollapseShade();
     }
 
+    /**
+     * When back progress is at 100%, the onBackProgressed animation driver inside
+     * NotificationPanelViewController should be invoked appropriately (with 1.0f passed in).
+     */
+    @Test
+    public void testPredictiveBackAnimation_progressMaxScalesPanel() {
+        mCentralSurfaces.setNotificationShadeWindowViewController(
+                mNotificationShadeWindowViewController);
+        mCentralSurfaces.handleVisibleToUserChanged(true);
+        verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
+                eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT),
+                mOnBackInvokedCallback.capture());
+
+        OnBackAnimationCallback onBackAnimationCallback =
+                (OnBackAnimationCallback) (mOnBackInvokedCallback.getValue());
+        when(mNotificationPanelViewController.canPanelBeCollapsed()).thenReturn(true);
+
+        BackEvent fakeSwipeInFromLeftEdge = new BackEvent(20.0f, 100.0f, 1.0f, BackEvent.EDGE_LEFT);
+        onBackAnimationCallback.onBackProgressed(fakeSwipeInFromLeftEdge);
+        verify(mNotificationPanelViewController).onBackProgressed(eq(1.0f));
+    }
+
+    /**
+     * When back progress is at 0%, the onBackProgressed animation driver inside
+     * NotificationPanelViewController should be invoked appropriately (with 0.0f passed in).
+     */
+    @Test
+    public void testPredictiveBackAnimation_progressMinScalesPanel() {
+        mCentralSurfaces.setNotificationShadeWindowViewController(
+                mNotificationShadeWindowViewController);
+        mCentralSurfaces.handleVisibleToUserChanged(true);
+        verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback(
+                eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT),
+                mOnBackInvokedCallback.capture());
+
+        OnBackAnimationCallback onBackAnimationCallback =
+                (OnBackAnimationCallback) (mOnBackInvokedCallback.getValue());
+        when(mNotificationPanelViewController.canPanelBeCollapsed()).thenReturn(true);
+
+        BackEvent fakeSwipeInFromLeftEdge = new BackEvent(20.0f, 10.0f, 0.0f, BackEvent.EDGE_LEFT);
+        onBackAnimationCallback.onBackProgressed(fakeSwipeInFromLeftEdge);
+        verify(mNotificationPanelViewController).onBackProgressed(eq(0.0f));
+    }
+
     @Test
     public void testPanelOpenForHeadsUp() {
         when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
@@ -1027,6 +1080,17 @@
     }
 
     @Test
+    public void testSetDozingNotUnlocking_transitionToAuthScrimmed_cancelKeyguardFadingAway() {
+        when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(true);
+        when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true);
+
+        mCentralSurfaces.updateScrimController();
+
+        verify(mScrimController).transitionTo(eq(ScrimState.AUTH_SCRIMMED_SHADE));
+        verify(mStatusBarKeyguardViewManager).onKeyguardFadedAway();
+    }
+
+    @Test
     public void testShowKeyguardImplementation_setsState() {
         when(mLockscreenUserManager.getCurrentProfiles()).thenReturn(new SparseArray<>());
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
index 305b9fe..6b18169 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicyTest.kt
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone
 
 import android.app.AlarmManager
-import android.app.IActivityManager
 import android.app.admin.DevicePolicyManager
 import android.content.SharedPreferences
 import android.os.UserManager
@@ -87,7 +86,6 @@
     @Mock private lateinit var keyguardStateController: KeyguardStateController
     @Mock private lateinit var locationController: LocationController
     @Mock private lateinit var sensorPrivacyController: SensorPrivacyController
-    @Mock private lateinit var iActivityManager: IActivityManager
     @Mock private lateinit var alarmManager: AlarmManager
     @Mock private lateinit var userManager: UserManager
     @Mock private lateinit var userTracker: UserTracker
@@ -176,6 +174,7 @@
             commandQueue,
             broadcastDispatcher,
             executor,
+            executor,
             testableLooper.looper,
             context.resources,
             castController,
@@ -190,7 +189,6 @@
             keyguardStateController,
             locationController,
             sensorPrivacyController,
-            iActivityManager,
             alarmManager,
             userManager,
             userTracker,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index c0537a6..180d9f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -24,6 +24,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyFloat;
@@ -58,7 +60,12 @@
 import com.android.systemui.animation.ShadeInterpolation;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
+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.PrimaryBouncerToGoneTransitionViewModel;
 import com.android.systemui.scrim.ScrimView;
 import com.android.systemui.statusbar.policy.FakeConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -85,8 +92,10 @@
 import java.util.HashSet;
 import java.util.Map;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+
 @RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
 public class ScrimControllerTest extends SysuiTestCase {
 
@@ -115,6 +124,10 @@
     @Mock private DockManager mDockManager;
     @Mock private ScreenOffAnimationController mScreenOffAnimationController;
     @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+    @Mock private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
+    @Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
+    @Mock private CoroutineDispatcher mMainDispatcher;
+
     // TODO(b/204991468): Use a real PanelExpansionStateManager object once this bug is fixed. (The
     //   event-dispatch-on-registration pattern caused some of these unit tests to fail.)
     @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@@ -225,13 +238,20 @@
         when(mDelayedWakeLockBuilder.build()).thenReturn(mWakeLock);
         when(mDockManager.isDocked()).thenReturn(false);
 
+        when(mKeyguardTransitionInteractor.getPrimaryBouncerToGoneTransition())
+                .thenReturn(emptyFlow());
+        when(mPrimaryBouncerToGoneTransitionViewModel.getScrimAlpha()).thenReturn(emptyFlow());
+
         mScrimController = new ScrimController(mLightBarController,
                 mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
                 new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
                 mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
                 mScreenOffAnimationController,
                 mKeyguardUnlockAnimationController,
-                mStatusBarKeyguardViewManager);
+                mStatusBarKeyguardViewManager,
+                mPrimaryBouncerToGoneTransitionViewModel,
+                mKeyguardTransitionInteractor,
+                mMainDispatcher);
         mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
         mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
         mScrimController.setAnimatorListener(mAnimatorListener);
@@ -861,7 +881,10 @@
                 mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
                 mScreenOffAnimationController,
                 mKeyguardUnlockAnimationController,
-                mStatusBarKeyguardViewManager);
+                mStatusBarKeyguardViewManager,
+                mPrimaryBouncerToGoneTransitionViewModel,
+                mKeyguardTransitionInteractor,
+                mMainDispatcher);
         mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
         mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
         mScrimController.setAnimatorListener(mAnimatorListener);
@@ -1356,33 +1379,10 @@
     }
 
     @Test
-    public void notificationAlpha_unnocclusionAnimating_bouncerActive_usesKeyguardNotifAlpha() {
-        when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(true);
-        mScrimController.setClipsQsScrim(true);
-
-        mScrimController.transitionTo(ScrimState.KEYGUARD);
-        mScrimController.setUnocclusionAnimationRunning(true);
-
-        assertAlphaAfterExpansion(
-                mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0f);
-        assertAlphaAfterExpansion(
-                mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0.4f);
-        assertAlphaAfterExpansion(
-                mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 1.0f);
-
-        // Verify normal behavior after
-        mScrimController.setUnocclusionAnimationRunning(false);
-        float expansion = 0.4f;
-        float alpha = 1 - BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion);
-        assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion);
-    }
-
-    @Test
     public void notificationAlpha_unnocclusionAnimating_bouncerNotActive_usesKeyguardNotifAlpha() {
         when(mStatusBarKeyguardViewManager.isPrimaryBouncerInTransit()).thenReturn(false);
 
         mScrimController.transitionTo(ScrimState.KEYGUARD);
-        mScrimController.setUnocclusionAnimationRunning(true);
 
         assertAlphaAfterExpansion(
                 mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 0f);
@@ -1392,7 +1392,6 @@
                 mNotificationsScrim, ScrimState.KEYGUARD.getNotifAlpha(), /* expansion */ 1.0f);
 
         // Verify normal behavior after
-        mScrimController.setUnocclusionAnimationRunning(false);
         float expansion = 0.4f;
         float alpha = 1 - ShadeInterpolation.getNotificationScrimAlpha(expansion);
         assertAlphaAfterExpansion(mNotificationsScrim, alpha, expansion);
@@ -1598,7 +1597,6 @@
 
     @Test
     public void setUnOccludingAnimationKeyguard() {
-        mScrimController.setUnocclusionAnimationRunning(true);
         mScrimController.transitionTo(ScrimState.KEYGUARD);
         finishAnimationsImmediately();
         assertThat(mNotificationsScrim.getViewAlpha())
@@ -1654,6 +1652,18 @@
         assertScrimAlpha(mScrimBehind, 0);
     }
 
+    @Test
+    public void ignoreTransitionRequestWhileKeyguardTransitionRunning() {
+        mScrimController.transitionTo(ScrimState.UNLOCKED);
+        mScrimController.mPrimaryBouncerToGoneTransition.accept(
+                new TransitionStep(KeyguardState.PRIMARY_BOUNCER, KeyguardState.GONE, 0f,
+                        TransitionState.RUNNING, "ScrimControllerTest"));
+
+        // This request should not happen
+        mScrimController.transitionTo(ScrimState.BOUNCER);
+        assertThat(mScrimController.getState()).isEqualTo(ScrimState.UNLOCKED);
+    }
+
     private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
         mScrimController.setRawPanelExpansionFraction(expansion);
         finishAnimationsImmediately();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 1aad83e..158e9ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -368,17 +368,6 @@
     }
 
     @Test
-    public void setOccluded_animatesPanelExpansion_onlyIfBouncerHidden() {
-        mStatusBarKeyguardViewManager.setOccluded(false /* occluded */, true /* animated */);
-        verify(mCentralSurfaces).animateKeyguardUnoccluding();
-
-        when(mPrimaryBouncerInteractor.isFullyShowing()).thenReturn(true);
-        clearInvocations(mCentralSurfaces);
-        mStatusBarKeyguardViewManager.setOccluded(false /* occluded */, true /* animated */);
-        verify(mCentralSurfaces, never()).animateKeyguardUnoccluding();
-    }
-
-    @Test
     public void setOccluded_onKeyguardOccludedChangedCalled() {
         clearInvocations(mKeyguardStateController);
         clearInvocations(mKeyguardUpdateMonitor);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index 00ce412..b072dee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -239,6 +239,7 @@
          *    list2 = [false, true]
          *    list3 = [a, b, c]
          * ```
+         *
          * We'll generate test cases for:
          *
          * Test (1, false, a) Test (2, false, a) Test (3, false, a) Test (1, true, a) Test (1,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
index 5288608..0413d92 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
@@ -25,7 +25,6 @@
 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
 import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
 import com.android.systemui.unfold.updates.FOLD_UPDATE_START_OPENING
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
 import com.android.systemui.unfold.util.TestFoldStateProvider
 import org.junit.Before
 import org.junit.Test
@@ -50,7 +49,7 @@
         runOnMainThreadWithInterval(
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
             { foldStateProvider.sendHingeAngleUpdate(10f) },
-            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendUnfoldedScreenAvailable() },
             { foldStateProvider.sendHingeAngleUpdate(90f) },
             { foldStateProvider.sendHingeAngleUpdate(180f) },
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
@@ -67,7 +66,7 @@
         runOnMainThreadWithInterval(
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
             { foldStateProvider.sendHingeAngleUpdate(10f) },
-            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendUnfoldedScreenAvailable() },
             { foldStateProvider.sendHingeAngleUpdate(90f) },
             { foldStateProvider.sendHingeAngleUpdate(180f) },
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
@@ -84,7 +83,7 @@
             { foldStateProvider.sendHingeAngleUpdate(90f) },
             { foldStateProvider.sendHingeAngleUpdate(180f) },
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN) },
-            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendUnfoldedScreenAvailable() },
         )
 
         with(listener.ensureTransitionFinished()) {
@@ -113,7 +112,7 @@
     fun testUnfoldAndStopUnfolding_finishesTheUnfoldTransition() {
         runOnMainThreadWithInterval(
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
-            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendUnfoldedScreenAvailable() },
             { foldStateProvider.sendHingeAngleUpdate(10f) },
             { foldStateProvider.sendHingeAngleUpdate(90f) },
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN) },
@@ -129,7 +128,7 @@
     fun testFoldImmediatelyAfterUnfold_runsFoldAnimation() {
         runOnMainThreadWithInterval(
             { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_START_OPENING) },
-            { foldStateProvider.sendFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) },
+            { foldStateProvider.sendUnfoldedScreenAvailable() },
             { foldStateProvider.sendHingeAngleUpdate(10f) },
             { foldStateProvider.sendHingeAngleUpdate(90f) },
             {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
index 6086e16..8476d0d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider
 import com.android.systemui.unfold.updates.FoldProvider.FoldCallback
 import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListener
+import com.android.systemui.unfold.updates.hinge.FULLY_OPEN_DEGREES
 import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
 import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
 import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
@@ -71,6 +72,7 @@
 
     private val foldUpdates: MutableList<Int> = arrayListOf()
     private val hingeAngleUpdates: MutableList<Float> = arrayListOf()
+    private val unfoldedScreenAvailabilityUpdates: MutableList<Unit> = arrayListOf()
 
     private var scheduledRunnable: Runnable? = null
     private var scheduledRunnableDelay: Long? = null
@@ -106,6 +108,10 @@
                 override fun onFoldUpdate(update: Int) {
                     foldUpdates.add(update)
                 }
+
+                override fun onUnfoldedScreenAvailable() {
+                    unfoldedScreenAvailabilityUpdates.add(Unit)
+                }
             })
         foldStateProvider.start()
 
@@ -156,8 +162,8 @@
         sendHingeAngleEvent(10)
         screenOnStatusProvider.notifyScreenTurnedOn()
 
-        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING,
-                FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE)
+        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING)
+        assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
     }
 
     @Test
@@ -174,8 +180,9 @@
         sendHingeAngleEvent(40)
         sendHingeAngleEvent(10)
 
-        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_OPENING,
-                FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE, FOLD_UPDATE_START_CLOSING)
+        assertThat(foldUpdates)
+                .containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_START_CLOSING)
+        assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
     }
 
     @Test
@@ -223,7 +230,7 @@
 
         fireScreenOnEvent()
 
-        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE)
+        assertThat(unfoldedScreenAvailabilityUpdates).hasSize(1)
     }
 
     @Test
@@ -277,7 +284,7 @@
 
     @Test
     fun startClosingEvent_afterTimeout_finishHalfOpenEventEmitted() {
-        sendHingeAngleEvent(90)
+        setInitialHingeAngle(90)
         sendHingeAngleEvent(80)
 
         simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS)
@@ -288,7 +295,7 @@
 
     @Test
     fun startClosingEvent_beforeTimeout_abortNotEmitted() {
-        sendHingeAngleEvent(90)
+        setInitialHingeAngle(90)
         sendHingeAngleEvent(80)
 
         simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS - 1)
@@ -298,7 +305,7 @@
 
     @Test
     fun startClosingEvent_eventBeforeTimeout_oneEventEmitted() {
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
         sendHingeAngleEvent(90)
 
         simulateTimeout(HALF_OPENED_TIMEOUT_MILLIS - 1)
@@ -309,7 +316,7 @@
 
     @Test
     fun startClosingEvent_timeoutAfterTimeoutRescheduled_finishHalfOpenStateEmitted() {
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
         sendHingeAngleEvent(90)
 
         // The timeout should not trigger here.
@@ -323,7 +330,7 @@
 
     @Test
     fun startClosingEvent_shortTimeBetween_emitsOnlyOneEvents() {
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(90)
         sendHingeAngleEvent(80)
@@ -334,20 +341,19 @@
     @Test
     fun startClosingEvent_whileClosing_emittedDespiteInitialAngle() {
         val maxAngle = 180 - FULLY_OPEN_THRESHOLD_DEGREES.toInt()
-        for (i in 1..maxAngle) {
-            foldUpdates.clear()
-
-            simulateFolding(startAngle = i)
+        val minAngle = Math.ceil(HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toDouble()).toInt() + 1
+        for (startAngle in minAngle..maxAngle) {
+            setInitialHingeAngle(startAngle)
+            sendHingeAngleEvent(startAngle - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
 
             assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
-            simulateTimeout() // Timeout to set the state to aborted.
         }
     }
 
     @Test
     fun startClosingEvent_whileNotOnLauncher_doesNotTriggerBeforeThreshold() {
         setupForegroundActivityType(isHomeActivity = false)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -357,7 +363,7 @@
     @Test
     fun startClosingEvent_whileActivityTypeNotAvailable_triggerBeforeThreshold() {
         setupForegroundActivityType(isHomeActivity = null)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -367,7 +373,7 @@
     @Test
     fun startClosingEvent_whileOnLauncher_doesTriggerBeforeThreshold() {
         setupForegroundActivityType(isHomeActivity = true)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -377,9 +383,11 @@
     @Test
     fun startClosingEvent_whileNotOnLauncher_triggersAfterThreshold() {
         setupForegroundActivityType(isHomeActivity = false)
-        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+        setInitialHingeAngle(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
 
-        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+        sendHingeAngleEvent(
+                START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
+                        HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
 
         assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
     }
@@ -388,7 +396,7 @@
     fun startClosingEvent_whileNotOnKeyguardAndNotOnLauncher_doesNotTriggerBeforeThreshold() {
         setKeyguardVisibility(visible = false)
         setupForegroundActivityType(isHomeActivity = false)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -398,7 +406,7 @@
     @Test
     fun startClosingEvent_whileKeyguardStateNotAvailable_triggerBeforeThreshold() {
         setKeyguardVisibility(visible = null)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -408,7 +416,7 @@
     @Test
     fun startClosingEvent_whileonKeyguard_doesTriggerBeforeThreshold() {
         setKeyguardVisibility(visible = true)
-        sendHingeAngleEvent(180)
+        setInitialHingeAngle(180)
 
         sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)
 
@@ -418,9 +426,59 @@
     @Test
     fun startClosingEvent_whileNotOnKeyguard_triggersAfterThreshold() {
         setKeyguardVisibility(visible = false)
-        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
+        setInitialHingeAngle(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)
 
-        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)
+        sendHingeAngleEvent(
+                START_CLOSING_ON_APPS_THRESHOLD_DEGREES -
+                        HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES.toInt() - 1)
+
+        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+    }
+
+    @Test
+    fun startClosingEvent_doesNotTriggerBelowThreshold() {
+        val thresholdAngle = (FULLY_OPEN_DEGREES - FULLY_OPEN_THRESHOLD_DEGREES).toInt()
+        setInitialHingeAngle(180)
+        sendHingeAngleEvent(thresholdAngle + 1)
+
+        assertThat(foldUpdates).isEmpty()
+    }
+
+    @Test
+    fun startClosingEvent_triggersAfterThreshold() {
+        val thresholdAngle = (FULLY_OPEN_DEGREES - FULLY_OPEN_THRESHOLD_DEGREES).toInt()
+        setInitialHingeAngle(180)
+        sendHingeAngleEvent(thresholdAngle + 1)
+        sendHingeAngleEvent(thresholdAngle - 1)
+
+        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+    }
+
+    @Test
+    fun startClosingEvent_triggersAfterThreshold_fromHalfOpen() {
+        setInitialHingeAngle(120)
+        sendHingeAngleEvent((120 - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES + 1).toInt())
+        assertThat(foldUpdates).isEmpty()
+        sendHingeAngleEvent((120 - HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES - 1).toInt())
+
+        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
+    }
+
+    @Test
+    fun startOpeningAndClosingEvents_triggerWithOpenAndClose() {
+        setInitialHingeAngle(120)
+        sendHingeAngleEvent(130)
+        sendHingeAngleEvent(120)
+        assertThat(foldUpdates)
+                .containsExactly(FOLD_UPDATE_START_OPENING, FOLD_UPDATE_START_CLOSING)
+    }
+
+    @Test
+    fun startClosingEvent_notInterrupted_whenAngleIsSlightlyIncreased() {
+        setInitialHingeAngle(120)
+        sendHingeAngleEvent(110)
+        sendHingeAngleEvent(111)
+        sendHingeAngleEvent(100)
 
         assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
     }
@@ -504,11 +562,6 @@
         }
     }
 
-    private fun simulateFolding(startAngle: Int) {
-        sendHingeAngleEvent(startAngle)
-        sendHingeAngleEvent(startAngle - 1)
-    }
-
     private fun setFoldState(folded: Boolean) {
         foldProvider.notifyFolded(folded)
     }
@@ -521,6 +574,17 @@
         testHingeAngleProvider.notifyAngle(angle.toFloat())
     }
 
+    private fun setInitialHingeAngle(angle: Int) {
+        setFoldState(angle == 0)
+        sendHingeAngleEvent(angle)
+        if (scheduledRunnableDelay != null) {
+            simulateTimeout()
+        }
+        hingeAngleUpdates.clear()
+        foldUpdates.clear()
+        unfoldedScreenAvailabilityUpdates.clear()
+    }
+
     private class TestFoldProvider : FoldProvider {
         private val callbacks = arrayListOf<FoldCallback>()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
index a064e8c..fbb0e5a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
@@ -57,4 +57,8 @@
     fun sendHingeAngleUpdate(angle: Float) {
         listeners.forEach { it.onHingeAngleUpdate(angle) }
     }
+
+    fun sendUnfoldedScreenAvailable() {
+        listeners.forEach { it.onUnfoldedScreenAvailable() }
+    }
 }
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 9312643..e2f3cf7 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,10 +17,7 @@
 
 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
@@ -44,14 +41,8 @@
 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
 
@@ -60,8 +51,6 @@
 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
 
@@ -235,30 +224,31 @@
     }
 
     @Test
-    fun userSwitchingInProgress_registersOnlyOneUserSwitchObserver() = runSelfCancelingTest {
+    fun userSwitchingInProgress_registersUserTrackerCallback() = runSelfCancelingTest {
         underTest = create(this)
 
         underTest.userSwitchingInProgress.launchIn(this)
         underTest.userSwitchingInProgress.launchIn(this)
         underTest.userSwitchingInProgress.launchIn(this)
 
-        verify(activityManager, times(1)).registerUserSwitchObserver(any(), anyString())
+        // Two callbacks registered - one for observing user switching and one for observing the
+        // selected user
+        assertThat(tracker.callbacks.size).isEqualTo(2)
     }
 
     @Test
-    fun userSwitchingInProgress_propagatesStateFromActivityManager() = runSelfCancelingTest {
+    fun userSwitchingInProgress_propagatesStateFromUserTracker() = runSelfCancelingTest {
         underTest = create(this)
-        verify(activityManager)
-            .registerUserSwitchObserver(userSwitchObserver.capture(), anyString())
+        assertThat(tracker.callbacks.size).isEqualTo(2)
 
-        userSwitchObserver.value.onUserSwitching(0, mock(IRemoteCallback::class.java))
+        tracker.onUserChanging(0)
 
         var mostRecentSwitchingValue = false
         underTest.userSwitchingInProgress.onEach { mostRecentSwitchingValue = it }.launchIn(this)
 
         assertThat(mostRecentSwitchingValue).isTrue()
 
-        userSwitchObserver.value.onUserSwitchComplete(0)
+        tracker.onUserChanged(0)
         assertThat(mostRecentSwitchingValue).isFalse()
     }
 
@@ -338,7 +328,6 @@
             backgroundDispatcher = IMMEDIATE,
             globalSettings = globalSettings,
             tracker = tracker,
-            activityManager = activityManager,
             featureFlags = featureFlags,
         )
     }
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 9b4f496..c2947b4 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
@@ -29,6 +29,7 @@
 
 /**
  * Collect [flow] in a new [Job] and return a getter for the last collected value.
+ *
  * ```
  * fun myTest() = runTest {
  *   // ...
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
index 01dac36..d4b1701 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeBiometricSettingsRepository.kt
@@ -21,6 +21,7 @@
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.flowOf
 
 class FakeBiometricSettingsRepository : BiometricSettingsRepository {
 
@@ -42,6 +43,9 @@
     override val isFingerprintEnabledByDevicePolicy =
         _isFingerprintEnabledByDevicePolicy.asStateFlow()
 
+    override val isFaceAuthSupportedInCurrentPosture: Flow<Boolean>
+        get() = flowOf(true)
+
     fun setFingerprintEnrolled(isFingerprintEnrolled: Boolean) {
         _isFingerprintEnrolled.value = isFingerprintEnrolled
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.kt
new file mode 100644
index 0000000..914c786
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDevicePostureRepository.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.keyguard.data.repository
+
+import com.android.systemui.keyguard.shared.model.DevicePosture
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class FakeDevicePostureRepository : DevicePostureRepository {
+    private val _currentDevicePosture = MutableStateFlow(DevicePosture.UNKNOWN)
+    override val currentDevicePosture: Flow<DevicePosture>
+        get() = _currentDevicePosture
+
+    fun setCurrentPosture(posture: DevicePosture) {
+        _currentDevicePosture.value = posture
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 1a371c7..194ed02 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -47,6 +47,9 @@
     private val _isKeyguardShowing = MutableStateFlow(false)
     override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing
 
+    private val _isKeyguardUnlocked = MutableStateFlow(false)
+    override val isKeyguardUnlocked: Flow<Boolean> = _isKeyguardUnlocked
+
     private val _isKeyguardOccluded = MutableStateFlow(false)
     override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
index eac1bd1..16442bb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardTransitionRepository.kt
@@ -37,7 +37,7 @@
         _transitions.emit(step)
     }
 
-    override fun startTransition(info: TransitionInfo): UUID? {
+    override fun startTransition(info: TransitionInfo, resetIfCanceled: Boolean): UUID? {
         return null
     }
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
index 251014f..4242c16 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/FakeUserTracker.kt
@@ -22,6 +22,7 @@
 import android.os.UserHandle
 import android.test.mock.MockContentResolver
 import com.android.systemui.util.mockito.mock
+import java.util.concurrent.CountDownLatch
 import java.util.concurrent.Executor
 
 /** A fake [UserTracker] to be used in tests. */
@@ -66,11 +67,19 @@
         _userId = _userInfo.id
         _userHandle = UserHandle.of(_userId)
 
+        onUserChanging()
+        onUserChanged()
+    }
+
+    fun onUserChanging(userId: Int = _userId) {
         val copy = callbacks.toList()
-        copy.forEach {
-            it.onUserChanging(_userId, userContext)
-            it.onUserChanged(_userId, userContext)
-        }
+        val latch = CountDownLatch(copy.size)
+        copy.forEach { it.onUserChanging(userId, userContext, latch) }
+    }
+
+    fun onUserChanged(userId: Int = _userId) {
+        val copy = callbacks.toList()
+        copy.forEach { it.onUserChanged(userId, userContext) }
     }
 
     fun onProfileChanged() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt
new file mode 100644
index 0000000..0c9ce0f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSystemUIDialogController.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.util
+
+import android.content.DialogInterface
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.verify
+import org.mockito.stubbing.Stubber
+
+class FakeSystemUIDialogController {
+
+    val dialog: SystemUIDialog = mock()
+
+    private val clickListeners: MutableMap<Int, DialogInterface.OnClickListener> = mutableMapOf()
+
+    init {
+        saveListener(DialogInterface.BUTTON_POSITIVE)
+            .whenever(dialog)
+            .setPositiveButton(any(), any())
+        saveListener(DialogInterface.BUTTON_POSITIVE)
+            .whenever(dialog)
+            .setPositiveButton(any(), any(), any())
+
+        saveListener(DialogInterface.BUTTON_NEGATIVE)
+            .whenever(dialog)
+            .setNegativeButton(any(), any())
+        saveListener(DialogInterface.BUTTON_NEGATIVE)
+            .whenever(dialog)
+            .setNegativeButton(any(), any(), any())
+
+        saveListener(DialogInterface.BUTTON_NEUTRAL).whenever(dialog).setNeutralButton(any(), any())
+        saveListener(DialogInterface.BUTTON_NEUTRAL)
+            .whenever(dialog)
+            .setNeutralButton(any(), any(), any())
+    }
+
+    fun clickNegative() {
+        performClick(DialogInterface.BUTTON_NEGATIVE, "This dialog has no negative button")
+    }
+
+    fun clickPositive() {
+        performClick(DialogInterface.BUTTON_POSITIVE, "This dialog has no positive button")
+    }
+
+    fun clickNeutral() {
+        performClick(DialogInterface.BUTTON_NEUTRAL, "This dialog has no neutral button")
+    }
+
+    fun cancel() {
+        val captor = ArgumentCaptor.forClass(DialogInterface.OnCancelListener::class.java)
+        verify(dialog).setOnCancelListener(captor.capture())
+        captor.value.onCancel(dialog)
+    }
+
+    private fun performClick(which: Int, errorMessage: String) {
+        clickListeners
+            .getOrElse(which) { throw IllegalAccessException(errorMessage) }
+            .onClick(dialog, which)
+    }
+
+    private fun saveListener(which: Int): Stubber = doAnswer {
+        val listener = it.getArgument<DialogInterface.OnClickListener>(1)
+        clickListeners[which] = listener
+        Unit
+    }
+}
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
index 4622464..c437e5c 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/FixedTimingTransitionProgressProvider.kt
@@ -21,7 +21,6 @@
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
 import com.android.systemui.unfold.updates.FoldStateProvider
 import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
 import javax.inject.Inject
@@ -59,12 +58,15 @@
     }
 
     override fun onFoldUpdate(@FoldUpdate update: Int) {
-        when (update) {
-            FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> animator.start()
-            FOLD_UPDATE_FINISH_CLOSED -> animator.cancel()
+        if (update == FOLD_UPDATE_FINISH_CLOSED) {
+             animator.cancel()
         }
     }
 
+    override fun onUnfoldedScreenAvailable() {
+        animator.start()
+    }
+
     override fun addCallback(listener: TransitionProgressListener) {
         listeners.add(listener)
     }
@@ -73,8 +75,6 @@
         listeners.remove(listener)
     }
 
-    override fun onHingeAngleUpdate(angle: Float) {}
-
     private object AnimationProgressProperty :
         FloatProperty<FixedTimingTransitionProgressProvider>("animation_progress") {
 
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
index 6ffbe5a..d19b414 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
@@ -28,7 +28,6 @@
 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_FULL_OPEN
 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_HALF_OPEN
 import com.android.systemui.unfold.updates.FOLD_UPDATE_START_CLOSING
-import com.android.systemui.unfold.updates.FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE
 import com.android.systemui.unfold.updates.FoldStateProvider
 import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
 import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdatesListener
@@ -78,21 +77,11 @@
 
     override fun onFoldUpdate(@FoldUpdate update: Int) {
         when (update) {
-            FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> {
-                startTransition(startValue = 0f)
-
-                // Stop the animation if the device has already opened by the time when
-                // the display is available as we won't receive the full open event anymore
-                if (foldStateProvider.isFinishedOpening) {
-                    cancelTransition(endValue = 1f, animate = true)
-                }
-            }
             FOLD_UPDATE_FINISH_FULL_OPEN, FOLD_UPDATE_FINISH_HALF_OPEN -> {
                 // Do not cancel if we haven't started the transition yet.
                 // This could happen when we fully unfolded the device before the screen
                 // became available. In this case we start and immediately cancel the animation
-                // in FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE event handler, so we don't need to
-                // cancel it here.
+                // in onUnfoldedScreenAvailable event handler, so we don't need to cancel it here.
                 if (isTransitionRunning) {
                     cancelTransition(endValue = 1f, animate = true)
                 }
@@ -125,6 +114,16 @@
         }
     }
 
+    override fun onUnfoldedScreenAvailable() {
+        startTransition(startValue = 0f)
+
+        // Stop the animation if the device has already opened by the time when
+        // the display is available as we won't receive the full open event anymore
+        if (foldStateProvider.isFinishedOpening) {
+            cancelTransition(endValue = 1f, animate = true)
+        }
+    }
+
     private fun cancelTransition(endValue: Float, animate: Boolean) {
         if (isTransitionRunning && animate) {
             if (endValue == 1.0f && !isAnimatedCancelRunning) {
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
index 97c9ba9..82fd225 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
@@ -54,6 +54,7 @@
     @FoldUpdate private var lastFoldUpdate: Int? = null
 
     @FloatRange(from = 0.0, to = 180.0) private var lastHingeAngle: Float = 0f
+    @FloatRange(from = 0.0, to = 180.0) private var lastHingeAngleBeforeTransition: Float = 0f
 
     private val hingeAngleListener = HingeAngleListener()
     private val screenListener = ScreenStatusListener()
@@ -112,29 +113,45 @@
 
     private fun onHingeAngle(angle: Float) {
         if (DEBUG) {
-            Log.d(TAG, "Hinge angle: $angle, lastHingeAngle: $lastHingeAngle")
+            Log.d(
+                TAG,
+                "Hinge angle: $angle, " +
+                    "lastHingeAngle: $lastHingeAngle, " +
+                    "lastHingeAngleBeforeTransition: $lastHingeAngleBeforeTransition"
+            )
             Trace.traceCounter(Trace.TRACE_TAG_APP, "hinge_angle", angle.toInt())
         }
 
-        val isClosing = angle < lastHingeAngle
+        val currentDirection =
+                if (angle < lastHingeAngle) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING
+        if (isTransitionInProgress && currentDirection != lastFoldUpdate) {
+            lastHingeAngleBeforeTransition = lastHingeAngle
+        }
+
+        val isClosing = angle < lastHingeAngleBeforeTransition
+        val transitionUpdate =
+                if (isClosing) FOLD_UPDATE_START_CLOSING else FOLD_UPDATE_START_OPENING
+        val angleChangeSurpassedThreshold =
+            Math.abs(angle - lastHingeAngleBeforeTransition) > HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES
         val isFullyOpened = FULLY_OPEN_DEGREES - angle < FULLY_OPEN_THRESHOLD_DEGREES
-        val closingEventDispatched = lastFoldUpdate == FOLD_UPDATE_START_CLOSING
+        val eventNotAlreadyDispatched = lastFoldUpdate != transitionUpdate
         val screenAvailableEventSent = isUnfoldHandled
 
-        if (isClosing // hinge angle should be decreasing since last update
-                && !closingEventDispatched  // we haven't sent closing event already
-                && !isFullyOpened // do not send closing event if we are in fully opened hinge
+        if (
+            angleChangeSurpassedThreshold && // Do not react immediately to small changes in angle
+                eventNotAlreadyDispatched && // we haven't sent transition event already
+                !isFullyOpened && // do not send transition event if we are in fully opened hinge
                                   // angle range as closing threshold could overlap this range
-                && screenAvailableEventSent // do not send closing event if we are still in
-                                            // the process of turning on the inner display
-                && isClosingThresholdMet(angle) // hinge angle is below certain threshold.
+                screenAvailableEventSent && // do not send transition event if we are still in the
+                                            // process of turning on the inner display
+                isClosingThresholdMet(angle) // hinge angle is below certain threshold.
         ) {
-            notifyFoldUpdate(FOLD_UPDATE_START_CLOSING)
+            notifyFoldUpdate(transitionUpdate, lastHingeAngle)
         }
 
         if (isTransitionInProgress) {
             if (isFullyOpened) {
-                notifyFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN)
+                notifyFoldUpdate(FOLD_UPDATE_FINISH_FULL_OPEN, angle)
                 cancelTimeout()
             } else {
                 // The timeout will trigger some constant time after the last angle update.
@@ -146,7 +163,7 @@
         outputListeners.forEach { it.onHingeAngleUpdate(angle) }
     }
 
-    private fun isClosingThresholdMet(currentAngle: Float) : Boolean {
+    private fun isClosingThresholdMet(currentAngle: Float): Boolean {
         val closingThreshold = getClosingThreshold()
         return closingThreshold == null || currentAngle < closingThreshold
     }
@@ -179,23 +196,29 @@
 
             if (isFolded) {
                 hingeAngleProvider.stop()
-                notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED)
+                notifyFoldUpdate(FOLD_UPDATE_FINISH_CLOSED, lastHingeAngle)
                 cancelTimeout()
                 isUnfoldHandled = false
             } else {
-                notifyFoldUpdate(FOLD_UPDATE_START_OPENING)
+                notifyFoldUpdate(FOLD_UPDATE_START_OPENING, lastHingeAngle)
                 rescheduleAbortAnimationTimeout()
                 hingeAngleProvider.start()
             }
         }
     }
 
-    private fun notifyFoldUpdate(@FoldUpdate update: Int) {
+    private fun notifyFoldUpdate(@FoldUpdate update: Int, angle: Float) {
         if (DEBUG) {
             Log.d(TAG, update.name())
         }
+        val previouslyTransitioning = isTransitionInProgress
+
         outputListeners.forEach { it.onFoldUpdate(update) }
         lastFoldUpdate = update
+
+        if (previouslyTransitioning != isTransitionInProgress) {
+            lastHingeAngleBeforeTransition = angle
+        }
     }
 
     private fun rescheduleAbortAnimationTimeout() {
@@ -209,7 +232,8 @@
         handler.removeCallbacks(timeoutRunnable)
     }
 
-    private fun cancelAnimation(): Unit = notifyFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN)
+    private fun cancelAnimation(): Unit =
+            notifyFoldUpdate(FOLD_UPDATE_FINISH_HALF_OPEN, lastHingeAngle)
 
     private inner class ScreenStatusListener : ScreenStatusProvider.ScreenListener {
 
@@ -221,7 +245,7 @@
             // receive 'folded' event. If SystemUI started when device is already folded it will
             // still receive 'folded' event on startup.
             if (!isFolded && !isUnfoldHandled) {
-                outputListeners.forEach { it.onFoldUpdate(FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE) }
+                outputListeners.forEach { it.onUnfoldedScreenAvailable() }
                 isUnfoldHandled = true
             }
         }
@@ -257,7 +281,6 @@
     when (this) {
         FOLD_UPDATE_START_OPENING -> "START_OPENING"
         FOLD_UPDATE_START_CLOSING -> "START_CLOSING"
-        FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE -> "UNFOLDED_SCREEN_AVAILABLE"
         FOLD_UPDATE_FINISH_HALF_OPEN -> "FINISH_HALF_OPEN"
         FOLD_UPDATE_FINISH_FULL_OPEN -> "FINISH_FULL_OPEN"
         FOLD_UPDATE_FINISH_CLOSED -> "FINISH_CLOSED"
@@ -270,5 +293,8 @@
 /** Threshold after which we consider the device fully unfolded. */
 @VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f
 
+/** Threshold after which hinge angle updates are considered. This is to eliminate noise. */
+@VisibleForTesting const val HINGE_ANGLE_CHANGE_THRESHOLD_DEGREES = 7.5f
+
 /** Fold animation on top of apps only when the angle exceeds this threshold. */
 @VisibleForTesting const val START_CLOSING_ON_APPS_THRESHOLD_DEGREES = 60
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
index c7a8bf3..0af372f 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
@@ -31,8 +31,9 @@
     val isFinishedOpening: Boolean
 
     interface FoldUpdatesListener {
-        fun onHingeAngleUpdate(@FloatRange(from = 0.0, to = 180.0) angle: Float)
-        fun onFoldUpdate(@FoldUpdate update: Int)
+        @JvmDefault fun onHingeAngleUpdate(@FloatRange(from = 0.0, to = 180.0) angle: Float) {}
+        @JvmDefault fun onFoldUpdate(@FoldUpdate update: Int) {}
+        @JvmDefault fun onUnfoldedScreenAvailable() {}
     }
 
     @IntDef(
@@ -40,7 +41,6 @@
             [
                 FOLD_UPDATE_START_OPENING,
                 FOLD_UPDATE_START_CLOSING,
-                FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE,
                 FOLD_UPDATE_FINISH_HALF_OPEN,
                 FOLD_UPDATE_FINISH_FULL_OPEN,
                 FOLD_UPDATE_FINISH_CLOSED])
@@ -50,7 +50,6 @@
 
 const val FOLD_UPDATE_START_OPENING = 0
 const val FOLD_UPDATE_START_CLOSING = 1
-const val FOLD_UPDATE_UNFOLDED_SCREEN_AVAILABLE = 2
-const val FOLD_UPDATE_FINISH_HALF_OPEN = 3
-const val FOLD_UPDATE_FINISH_FULL_OPEN = 4
-const val FOLD_UPDATE_FINISH_CLOSED = 5
+const val FOLD_UPDATE_FINISH_HALF_OPEN = 2
+const val FOLD_UPDATE_FINISH_FULL_OPEN = 3
+const val FOLD_UPDATE_FINISH_CLOSED = 4
diff --git a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
index b7bab3e..f9751d9 100644
--- a/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
+++ b/packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.kt
@@ -47,6 +47,7 @@
     /**
      * Sets the source for the unfold transition progress updates. Replaces current provider if it
      * is already set
+     *
      * @param provider transition provider that emits transition progress updates
      */
     fun setSourceProvider(provider: UnfoldTransitionProgressProvider?) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 1f8a779..7fba72b 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3801,6 +3801,7 @@
     public boolean registerProxyForDisplay(IAccessibilityServiceClient client, int displayId)
             throws RemoteException {
         mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
+        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
         if (client == null) {
             return false;
         }
@@ -3837,6 +3838,7 @@
     @Override
     public boolean unregisterProxyForDisplay(int displayId) {
         mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
+        mSecurityPolicy.enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
         final long identity = Binder.clearCallingIdentity();
         try {
             return mProxyManager.unregisterProxy(displayId);
@@ -3928,6 +3930,8 @@
                         mGlobalClients.getRegisteredCallbackCookie(i);
                 pw.append(Arrays.toString(client.mPackageNames));
             }
+            pw.println();
+            mProxyManager.dump(fd, pw, args);
         }
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index 094053e..0e25a06 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -910,6 +910,10 @@
             pw.println("     Top Focused Window Id = " + mTopFocusedWindowId);
             pw.println("     Accessibility Focused Window Id = " + mAccessibilityFocusedWindowId
                     + " ]");
+            if (mIsProxy) {
+                pw.println("Proxy accessibility focused window = "
+                        + mProxyDisplayAccessibilityFocusedWindow);
+            }
             pw.println();
             if (mWindows != null) {
                 final int windowCount = mWindows.size();
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
index 945d43b..b19a502 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyAccessibilityServiceConnection.java
@@ -38,14 +38,18 @@
 import android.os.RemoteException;
 import android.view.KeyEvent;
 import android.view.accessibility.AccessibilityDisplayProxy;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityWindowInfo;
 
 import androidx.annotation.Nullable;
 
 import com.android.internal.R;
+import com.android.internal.util.DumpUtils;
 import com.android.server.wm.WindowManagerInternal;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
@@ -61,6 +65,8 @@
  * TODO(241429275): Initialize this when a proxy is registered.
  */
 public class ProxyAccessibilityServiceConnection extends AccessibilityServiceConnection {
+    private static final String LOG_TAG = "ProxyAccessibilityServiceConnection";
+
     private int mDisplayId;
     private List<AccessibilityServiceInfo> mInstalledAndEnabledServices;
 
@@ -565,4 +571,25 @@
     public void setAnimationScale(float scale) throws UnsupportedOperationException {
         throw new UnsupportedOperationException("setAnimationScale is not supported");
     }
+
+    @Override
+    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+        if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
+        synchronized (mLock) {
+            pw.append("Proxy[displayId=" + mDisplayId);
+            pw.append(", feedbackType"
+                    + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
+            pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
+            pw.append(", eventTypes="
+                    + AccessibilityEvent.eventTypeToString(mEventTypes));
+            pw.append(", notificationTimeout=" + mNotificationTimeout);
+            pw.append(", focusStrokeWidth=").append(String.valueOf(mFocusStrokeWidth));
+            pw.append(", focusColor=").append(String.valueOf(mFocusColor));
+            pw.append(", installedAndEnabledServiceCount=").append(String.valueOf(
+                    mInstalledAndEnabledServices.size()));
+            pw.append(", installedAndEnabledServices=").append(
+                    mInstalledAndEnabledServices.toString());
+            pw.append("]");
+        }
+    }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
index 9d91d10..e258de1 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
@@ -23,6 +23,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.accessibility.AccessibilityEvent;
@@ -30,6 +31,8 @@
 
 import com.android.server.wm.WindowManagerInternal;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.List;
 
 /**
@@ -42,6 +45,9 @@
  * TODO(262244375): Add unit tests.
  */
 public class ProxyManager {
+    private static final boolean DEBUG = false;
+    private static final String LOG_TAG = "ProxyManager";
+
     // Names used to populate ComponentName and ResolveInfo in connection.mA11yServiceInfo and in
     // the infos of connection.setInstalledAndEnabledServices
     static final String PROXY_COMPONENT_PACKAGE_NAME = "ProxyPackage";
@@ -79,6 +85,9 @@
             AbstractAccessibilityServiceConnection.SystemSupport systemSupport,
             AccessibilityTrace trace,
             WindowManagerInternal windowManagerInternal) throws RemoteException {
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "Register proxy for display id: " + displayId);
+        }
 
         // Set a default AccessibilityServiceInfo that is used before the proxy's info is
         // populated. A proxy has the touch exploration and window capabilities.
@@ -134,6 +143,9 @@
             if (mProxyA11yServiceConnections.contains(displayId)) {
                 mProxyA11yServiceConnections.remove(displayId);
                 removed = true;
+                if (DEBUG) {
+                    Slog.v(LOG_TAG, "Unregister proxy for display id " + displayId);
+                }
             }
         }
         if (removed) {
@@ -155,19 +167,25 @@
      */
     public boolean isProxyed(int displayId) {
         synchronized (mLock) {
-            return mProxyA11yServiceConnections.contains(displayId);
+            final boolean tracked = mProxyA11yServiceConnections.contains(displayId);
+            if (DEBUG) {
+                Slog.v(LOG_TAG, "Tracking proxy display " + displayId + " : " + tracked);
+            }
+            return tracked;
         }
     }
 
     /**
-     * Sends AccessibilityEvents to all proxies.
-     * {@link android.view.accessibility.AccessibilityDisplayProxy} will filter based on display.
-     * TODO(b/250929565): Filtering should happen in the system, not in the proxy.
+     * Sends AccessibilityEvents to a proxy given the event's displayId.
      */
     public void sendAccessibilityEventLocked(AccessibilityEvent event) {
         final ProxyAccessibilityServiceConnection proxy =
                 mProxyA11yServiceConnections.get(event.getDisplayId());
         if (proxy != null) {
+            if (DEBUG) {
+                Slog.v(LOG_TAG, "Send proxy event " + event + " for display id "
+                        + event.getDisplayId());
+            }
             proxy.notifyAccessibilityEvent(event);
         }
     }
@@ -186,6 +204,9 @@
                 break;
             }
         }
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "At least one proxy can retrieve windows: " + observingWindows);
+        }
         return observingWindows;
     }
 
@@ -205,6 +226,14 @@
                 clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
             }
         }
+
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "Accessibility is enabled for all proxies: "
+                    + ((clientState & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0));
+            Slog.v(LOG_TAG, "Touch exploration is enabled for all proxies: "
+                    + ((clientState & AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED)
+                            != 0));
+        }
         return clientState;
         // TODO(b/254545943): When A11yManager is separated, include support for other properties.
     }
@@ -234,6 +263,10 @@
                     mProxyA11yServiceConnections.valueAt(i);
             relevantEventTypes |= proxy.getRelevantEventTypes();
         }
+        if (DEBUG) {
+            Slog.v(LOG_TAG, "Relevant event types for all proxies: "
+                    + AccessibilityEvent.eventTypeToString(relevantEventTypes));
+        }
         return relevantEventTypes;
     }
 
@@ -275,4 +308,25 @@
     void setAccessibilityInputFilter(AccessibilityInputFilter filter) {
         mA11yInputFilter = filter;
     }
+
+
+    /**
+     * Prints information belonging to each display that is controlled by an
+     * AccessibilityDisplayProxy.
+     */
+    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        synchronized (mLock) {
+            pw.println();
+            pw.println("Proxy manager state:");
+            pw.println("    Number of proxy connections: " + mProxyA11yServiceConnections.size());
+            pw.println("    Registered proxy connections:");
+            for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
+                final ProxyAccessibilityServiceConnection proxy =
+                        mProxyA11yServiceConnections.valueAt(i);
+                if (proxy != null) {
+                    proxy.dump(fd, pw, args);
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java
index 21b51b1..607439b 100644
--- a/services/companion/java/com/android/server/companion/virtual/InputController.java
+++ b/services/companion/java/com/android/server/companion/virtual/InputController.java
@@ -88,7 +88,7 @@
      */
     private static final int DEVICE_NAME_MAX_LENGTH = 80;
 
-    final Object mLock;
+    final Object mLock = new Object();
 
     /* Token -> file descriptor associations. */
     @GuardedBy("mLock")
@@ -101,18 +101,17 @@
     private final WindowManager mWindowManager;
     private final DeviceCreationThreadVerifier mThreadVerifier;
 
-    InputController(@NonNull Object lock, @NonNull Handler handler,
+    InputController(@NonNull Handler handler,
             @NonNull WindowManager windowManager) {
-        this(lock, new NativeWrapper(), handler, windowManager,
+        this(new NativeWrapper(), handler, windowManager,
                 // Verify that virtual devices are not created on the handler thread.
                 () -> !handler.getLooper().isCurrentThread());
     }
 
     @VisibleForTesting
-    InputController(@NonNull Object lock, @NonNull NativeWrapper nativeWrapper,
+    InputController(@NonNull NativeWrapper nativeWrapper,
             @NonNull Handler handler, @NonNull WindowManager windowManager,
             @NonNull DeviceCreationThreadVerifier threadVerifier) {
-        mLock = lock;
         mHandler = handler;
         mNativeWrapper = nativeWrapper;
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
diff --git a/services/companion/java/com/android/server/companion/virtual/SensorController.java b/services/companion/java/com/android/server/companion/virtual/SensorController.java
index 7804ebf..864fe0f 100644
--- a/services/companion/java/com/android/server/companion/virtual/SensorController.java
+++ b/services/companion/java/com/android/server/companion/virtual/SensorController.java
@@ -22,8 +22,11 @@
 import android.companion.virtual.sensor.VirtualSensor;
 import android.companion.virtual.sensor.VirtualSensorConfig;
 import android.companion.virtual.sensor.VirtualSensorEvent;
+import android.hardware.SensorDirectChannel;
 import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.SharedMemory;
 import android.util.ArrayMap;
 import android.util.Slog;
 
@@ -36,6 +39,7 @@
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /** Controls virtual sensors, including their lifecycle and sensor event dispatch. */
 public class SensorController {
@@ -47,6 +51,8 @@
     private static final int UNKNOWN_ERROR = (-2147483647 - 1); // INT32_MIN value
     private static final int BAD_VALUE = -22;
 
+    private static AtomicInteger sNextDirectChannelHandle = new AtomicInteger(1);
+
     private final Object mLock;
     private final int mVirtualDeviceId;
     @GuardedBy("mLock")
@@ -57,8 +63,6 @@
     private final SensorManagerInternal mSensorManagerInternal;
     private final VirtualDeviceManagerInternal mVdmInternal;
 
-
-
     public SensorController(@NonNull Object lock, int virtualDeviceId,
             @Nullable IVirtualSensorCallback virtualSensorCallback) {
         mLock = lock;
@@ -97,7 +101,7 @@
             throws SensorCreationException {
         final int handle = mSensorManagerInternal.createRuntimeSensor(mVirtualDeviceId,
                 config.getType(), config.getName(),
-                config.getVendor() == null ? "" : config.getVendor(),
+                config.getVendor() == null ? "" : config.getVendor(), config.getFlags(),
                 mRuntimeSensorCallback);
         if (handle <= 0) {
             throw new SensorCreationException("Received an invalid virtual sensor handle.");
@@ -212,6 +216,66 @@
             }
             return OK;
         }
+
+        @Override
+        public int onDirectChannelCreated(ParcelFileDescriptor fd) {
+            if (mCallback == null) {
+                Slog.e(TAG, "No sensor callback for virtual deviceId " + mVirtualDeviceId);
+                return BAD_VALUE;
+            } else if (fd == null) {
+                Slog.e(TAG, "Received invalid ParcelFileDescriptor");
+                return BAD_VALUE;
+            }
+            final int channelHandle = sNextDirectChannelHandle.getAndIncrement();
+            SharedMemory sharedMemory = SharedMemory.fromFileDescriptor(fd);
+            try {
+                mCallback.onDirectChannelCreated(channelHandle, sharedMemory);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to call sensor callback: " + e);
+                return UNKNOWN_ERROR;
+            }
+            return channelHandle;
+        }
+
+        @Override
+        public void onDirectChannelDestroyed(int channelHandle) {
+            if (mCallback == null) {
+                Slog.e(TAG, "No sensor callback for virtual deviceId " + mVirtualDeviceId);
+                return;
+            }
+            try {
+                mCallback.onDirectChannelDestroyed(channelHandle);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to call sensor callback: " + e);
+            }
+        }
+
+        @Override
+        public int onDirectChannelConfigured(int channelHandle, int sensorHandle,
+                @SensorDirectChannel.RateLevel int rateLevel) {
+            if (mCallback == null) {
+                Slog.e(TAG, "No runtime sensor callback configured.");
+                return BAD_VALUE;
+            }
+            VirtualSensor sensor = mVdmInternal.getVirtualSensor(mVirtualDeviceId, sensorHandle);
+            if (sensor == null) {
+                Slog.e(TAG, "No sensor found for deviceId=" + mVirtualDeviceId
+                        + " and sensor handle=" + sensorHandle);
+                return BAD_VALUE;
+            }
+            try {
+                mCallback.onDirectChannelConfigured(channelHandle, sensor, rateLevel, sensorHandle);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Failed to call sensor callback: " + e);
+                return UNKNOWN_ERROR;
+            }
+            if (rateLevel == SensorDirectChannel.RATE_STOP) {
+                return OK;
+            } else {
+                // Use the sensor handle as a report token, i.e. a unique identifier of the sensor.
+                return sensorHandle;
+            }
+        }
     }
 
     @VisibleForTesting
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 f650560..ee1b1fd 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -105,6 +105,14 @@
 
     private static final String TAG = "VirtualDeviceImpl";
 
+    private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS =
+            DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
+                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT
+                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
+                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL
+                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
+                    | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
+
     /**
      * Timeout until {@link #launchPendingIntent} stops waiting for an activity to be launched.
      */
@@ -251,7 +259,6 @@
         mDisplayManager = displayManager;
         if (inputController == null) {
             mInputController = new InputController(
-                    mVirtualDeviceLock,
                     context.getMainThreadHandler(),
                     context.getSystemService(WindowManager.class));
         } else {
@@ -281,7 +288,7 @@
      * device.
      */
     int getBaseVirtualDisplayFlags() {
-        int flags = 0;
+        int flags = DEFAULT_VIRTUAL_DISPLAY_FLAGS;
         if (mParams.getLockState() == VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED) {
             flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
         }
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
index ed5b858..3b1983f 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceManagerService.java
@@ -84,7 +84,7 @@
     private final PendingTrampolineMap mPendingTrampolines = new PendingTrampolineMap(mHandler);
 
     private static AtomicInteger sNextUniqueIndex = new AtomicInteger(
-            VirtualDeviceManager.DEVICE_ID_DEFAULT + 1);
+            Context.DEVICE_ID_DEFAULT + 1);
 
     /**
      * Mapping from device IDs to virtual devices.
@@ -327,7 +327,7 @@
         @Override // Binder call
         public int getDeviceIdForDisplayId(int displayId) {
             if (displayId == Display.INVALID_DISPLAY || displayId == Display.DEFAULT_DISPLAY) {
-                return VirtualDeviceManager.DEVICE_ID_DEFAULT;
+                return Context.DEVICE_ID_DEFAULT;
             }
             synchronized (mVirtualDeviceManagerLock) {
                 for (int i = 0; i < mVirtualDevices.size(); i++) {
@@ -337,7 +337,7 @@
                     }
                 }
             }
-            return VirtualDeviceManager.DEVICE_ID_DEFAULT;
+            return Context.DEVICE_ID_DEFAULT;
         }
 
         // Binder call
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 92e322f..e9a7f20 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -192,20 +192,21 @@
     private ArrayDeque<Bundle> mBatteryLevelsEventQueue;
     private long mLastBatteryLevelChangedSentMs;
 
-    private Bundle mBatteryChangedOptions = BroadcastOptions.makeRemovingMatchingFilter(
-            new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).setDeferUntilActive(true)
+    private Bundle mBatteryChangedOptions = BroadcastOptions.makeBasic()
+            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+            .setDeferUntilActive(true)
             .toBundle();
-    private Bundle mPowerConnectedOptions = BroadcastOptions.makeRemovingMatchingFilter(
-            new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).setDeferUntilActive(true)
+    /** Used for both connected/disconnected, so match using key */
+    private Bundle mPowerOptions = BroadcastOptions.makeBasic()
+            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+            .setDeliveryGroupMatchingKey("android", Intent.ACTION_POWER_CONNECTED)
+            .setDeferUntilActive(true)
             .toBundle();
-    private Bundle mPowerDisconnectedOptions = BroadcastOptions.makeRemovingMatchingFilter(
-            new IntentFilter(Intent.ACTION_POWER_CONNECTED)).setDeferUntilActive(true)
-            .toBundle();
-    private Bundle mBatteryLowOptions = BroadcastOptions.makeRemovingMatchingFilter(
-            new IntentFilter(Intent.ACTION_BATTERY_OKAY)).setDeferUntilActive(true)
-            .toBundle();
-    private Bundle mBatteryOkayOptions = BroadcastOptions.makeRemovingMatchingFilter(
-            new IntentFilter(Intent.ACTION_BATTERY_LOW)).setDeferUntilActive(true)
+    /** Used for both low/okay, so match using key */
+    private Bundle mBatteryOptions = BroadcastOptions.makeBasic()
+            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+            .setDeliveryGroupMatchingKey("android", Intent.ACTION_BATTERY_OKAY)
+            .setDeferUntilActive(true)
             .toBundle();
 
     private MetricsLogger mMetricsLogger;
@@ -636,7 +637,7 @@
                     @Override
                     public void run() {
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
-                                mPowerConnectedOptions);
+                                mPowerOptions);
                     }
                 });
             }
@@ -648,7 +649,7 @@
                     @Override
                     public void run() {
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
-                                mPowerDisconnectedOptions);
+                                mPowerOptions);
                     }
                 });
             }
@@ -662,7 +663,7 @@
                     @Override
                     public void run() {
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
-                                mBatteryLowOptions);
+                                mBatteryOptions);
                     }
                 });
             } else if (mSentLowBatteryBroadcast &&
@@ -675,7 +676,7 @@
                     @Override
                     public void run() {
                         mContext.sendBroadcastAsUser(statusIntent, UserHandle.ALL, null,
-                                mBatteryOkayOptions);
+                                mBatteryOptions);
                     }
                 });
             }
@@ -1210,6 +1211,11 @@
     }
 
     private final class Led {
+        // must match: config_notificationsBatteryLowBehavior in config.xml
+        static final int LOW_BATTERY_BEHAVIOR_DEFAULT = 0;
+        static final int LOW_BATTERY_BEHAVIOR_SOLID = 1;
+        static final int LOW_BATTERY_BEHAVIOR_FLASHING = 2;
+
         private final LogicalLight mBatteryLight;
 
         private final int mBatteryLowARGB;
@@ -1217,6 +1223,7 @@
         private final int mBatteryFullARGB;
         private final int mBatteryLedOn;
         private final int mBatteryLedOff;
+        private final int mBatteryLowBehavior;
 
         public Led(Context context, LightsManager lights) {
             mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY);
@@ -1233,6 +1240,8 @@
                     com.android.internal.R.integer.config_notificationsBatteryLedOff);
             mBatteryNearlyFullLevel = context.getResources().getInteger(
                     com.android.internal.R.integer.config_notificationsBatteryNearlyFullLevel);
+            mBatteryLowBehavior = context.getResources().getInteger(
+                    com.android.internal.R.integer.config_notificationsBatteryLowBehavior);
         }
 
         /**
@@ -1245,13 +1254,26 @@
             final int level = mHealthInfo.batteryLevel;
             final int status = mHealthInfo.batteryStatus;
             if (level < mLowBatteryWarningLevel) {
-                if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
-                    // Solid red when battery is charging
-                    mBatteryLight.setColor(mBatteryLowARGB);
-                } else {
-                    // Flash red when battery is low and not charging
-                    mBatteryLight.setFlashing(mBatteryLowARGB, LogicalLight.LIGHT_FLASH_TIMED,
-                            mBatteryLedOn, mBatteryLedOff);
+                switch (mBatteryLowBehavior) {
+                    case LOW_BATTERY_BEHAVIOR_SOLID:
+                        // Solid red when low battery
+                        mBatteryLight.setColor(mBatteryLowARGB);
+                        break;
+                    case LOW_BATTERY_BEHAVIOR_FLASHING:
+                        // Flash red when battery is low and not charging
+                        mBatteryLight.setFlashing(mBatteryLowARGB, LogicalLight.LIGHT_FLASH_TIMED,
+                                mBatteryLedOn, mBatteryLedOff);
+                        break;
+                    default:
+                        if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
+                            // Solid red when battery is charging
+                            mBatteryLight.setColor(mBatteryLowARGB);
+                        } else {
+                            // Flash red when battery is low and not charging
+                            mBatteryLight.setFlashing(mBatteryLowARGB,
+                                    LogicalLight.LIGHT_FLASH_TIMED, mBatteryLedOn, mBatteryLedOff);
+                        }
+                        break;
                 }
             } else if (status == BatteryManager.BATTERY_STATUS_CHARGING
                     || status == BatteryManager.BATTERY_STATUS_FULL) {
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index 2992bf9..3ecf933 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -34,7 +34,6 @@
 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;
@@ -117,14 +116,17 @@
     @VisibleForTesting
     static final String BINARY_HASH_ERROR = "SHA256HashError";
 
-    static final int MEASURE_APEX_AND_MODULES = 1;
-    static final int MEASURE_PRELOADS = 2;
-    static final int MEASURE_NEW_MBAS = 3;
-
     static final long RECORD_MEASUREMENTS_COOLDOWN_MS = 24 * 60 * 60 * 1000;
 
     static final String APEX_PRELOAD_LOCATION_ERROR = "could-not-be-determined";
 
+    // Copy from the atom. Consistent for both ApexInfoGathered and MobileBundledAppInfoGathered.
+    static final int DIGEST_ALGORITHM_UNKNOWN = 0;
+    static final int DIGEST_ALGORITHM_CHUNKED_SHA256 = 1;
+    static final int DIGEST_ALGORITHM_CHUNKED_SHA512 = 2;
+    static final int DIGEST_ALGORITHM_VERITY_CHUNKED_SHA256 = 3;
+    static final int DIGEST_ALGORITHM_SHA256 = 4;
+
     // used for indicating any type of error during MBA measurement
     static final int MBA_STATUS_ERROR = 0;
     // used for indicating factory condition preloads
@@ -226,9 +228,9 @@
                 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();
+                Digest digest = measureApk(split.getPath());
+                appInfo.digest = digest.value;
+                appInfo.digestAlgorithm = digest.algorithm;
 
                 results.add(appInfo);
             }
@@ -260,10 +262,9 @@
          * 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.
+         * @return a {@link #Digest} with preferred digest algorithm type and the value.
          */
-        private @Nullable Checksum measureApk(@NonNull String apkPath) {
+        private @Nullable Digest measureApk(@NonNull String apkPath) {
             // compute content digest
             Map<Integer, byte[]> contentDigests = computeApkContentDigest(apkPath);
             if (contentDigests == null) {
@@ -274,20 +275,20 @@
                 // And only one of them will be available per package.
                 if (contentDigests.containsKey(
                             ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256)) {
-                    return new Checksum(
-                            Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256,
+                    return new Digest(
+                            DIGEST_ALGORITHM_CHUNKED_SHA256,
                             contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256));
                 } else if (contentDigests.containsKey(
                         ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512)) {
-                    return new Checksum(
-                            Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512,
+                    return new Digest(
+                            DIGEST_ALGORITHM_CHUNKED_SHA512,
                             contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512));
                 }
             }
             // When something went wrong, fall back to simple sha256.
             byte[] digest = PackageUtils.computeSha256DigestForLargeFileAsBytes(apkPath,
                     PackageUtils.createLargeFileBuffer());
-            return new Checksum(Checksum.TYPE_WHOLE_SHA256, digest);
+            return new Digest(DIGEST_ALGORITHM_SHA256, digest);
         }
 
 
@@ -350,7 +351,7 @@
                 // lastly measure all newly installed MBAs
                 List<IBinaryTransparencyService.AppInfo> allMbaInfo =
                         collectAllSilentInstalledMbaInfo(packagesMeasured);
-                for (IBinaryTransparencyService.AppInfo appInfo : allUpdatedPreloadInfo) {
+                for (IBinaryTransparencyService.AppInfo appInfo : allMbaInfo) {
                     packagesMeasured.putBoolean(appInfo.packageName, true);
                     writeAppInfoToLog(appInfo);
                 }
@@ -381,7 +382,7 @@
                     Slog.w(TAG, "Skipping the missing APK in " + pkg.getPath());
                     continue;
                 }
-                Checksum apexChecksum = measureApk(pkg.getPath());
+                Digest apexChecksum = measureApk(pkg.getPath());
                 if (apexChecksum == null) {
                     Slog.w(TAG, "Skipping the missing APEX in " + pkg.getPath());
                     continue;
@@ -390,8 +391,8 @@
                 var apexInfo = new IBinaryTransparencyService.ApexInfo();
                 apexInfo.packageName = packageState.getPackageName();
                 apexInfo.longVersion = packageState.getVersionCode();
-                apexInfo.digest = apexChecksum.getValue();
-                apexInfo.digestAlgorithm = apexChecksum.getType();
+                apexInfo.digest = apexChecksum.value;
+                apexInfo.digestAlgorithm = apexChecksum.algorithm;
                 apexInfo.signerDigests =
                         computePackageSignerSha256Digests(packageState.getSigningInfo());
 
@@ -1691,4 +1692,14 @@
         }
         return slice.getList();
     }
+
+    private static class Digest {
+        public int algorithm;
+        public byte[] value;
+
+        Digest(int algorithm, byte[] value) {
+            this.algorithm = algorithm;
+            this.value = value;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 725ea5c..19e5cb1 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -79,6 +79,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.zip.GZIPOutputStream;
@@ -105,6 +106,10 @@
     // Size beyond which to force-compress newly added entries.
     private static final long COMPRESS_THRESHOLD_BYTES = 16_384;
 
+    // Tags that we should drop by default.
+    private static final List<String> DISABLED_BY_DEFAULT_TAGS =
+            List.of("data_app_wtf", "system_app_wtf", "system_server_wtf");
+
     // TODO: This implementation currently uses one file per entry, which is
     // inefficient for smallish entries -- consider using a single queue file
     // per tag (or even globally) instead.
@@ -549,8 +554,13 @@
     public boolean isTagEnabled(String tag) {
         final long token = Binder.clearCallingIdentity();
         try {
-            return !"disabled".equals(Settings.Global.getString(
+            if (DISABLED_BY_DEFAULT_TAGS.contains(tag)) {
+                return "enabled".equals(Settings.Global.getString(
                     mContentResolver, Settings.Global.DROPBOX_TAG_PREFIX + tag));
+            } else {
+                return !"disabled".equals(Settings.Global.getString(
+                    mContentResolver, Settings.Global.DROPBOX_TAG_PREFIX + tag));
+            }
         } finally {
             Binder.restoreCallingIdentity(token);
         }
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 3f1ad3a..2a46d86 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -16,18 +16,12 @@
 
 package com.android.server;
 
-import static android.content.IntentFilter.BLOCK_NULL_ACTION_INTENTS;
-
-import static com.android.internal.util.FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.Uri;
-import android.os.Binder;
-import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.FastImmutableArraySet;
@@ -40,7 +34,6 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.FastPrintWriter;
-import com.android.server.am.ActivityManagerUtils;
 import com.android.server.pm.Computer;
 import com.android.server.pm.snapshot.PackageDataSnapshot;
 
@@ -88,7 +81,7 @@
      * Returns whether an intent matches the IntentFilter with a pre-resolved type.
      */
     public static boolean intentMatchesFilter(
-            IntentFilter filter, Intent intent, String resolvedType, boolean blockNullAction) {
+            IntentFilter filter, Intent intent, String resolvedType) {
         final boolean debug = localLOGV
                 || ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
 
@@ -102,8 +95,7 @@
         }
 
         final int match = filter.match(intent.getAction(), resolvedType, intent.getScheme(),
-                intent.getData(), intent.getCategories(), TAG, /* supportWildcards */ false,
-                blockNullAction, null, null);
+                intent.getData(), intent.getCategories(), TAG);
 
         if (match >= 0) {
             if (debug) {
@@ -358,32 +350,14 @@
         return Collections.unmodifiableSet(mFilters);
     }
 
-    private boolean blockNullAction(Computer computer, Intent intent,
-            String resolvedType, int callingUid, boolean debug) {
-        if (intent.getAction() == null) {
-            final boolean blockNullAction = UserHandle.isCore(callingUid)
-                    || computer.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS, callingUid);
-            ActivityManagerUtils.logUnsafeIntentEvent(
-                    UNSAFE_INTENT_EVENT_REPORTED__EVENT_TYPE__NULL_ACTION_MATCH,
-                    callingUid, intent, resolvedType, blockNullAction);
-            if (blockNullAction) {
-                if (debug) Slog.v(TAG, "Skip matching filters: action is null");
-                return true;
-            }
-        }
-        return false;
-    }
-
     public List<R> queryIntentFromList(@NonNull Computer computer, Intent intent,
-            String resolvedType, boolean defaultOnly, ArrayList<F[]> listCut,
-            int callingUid, @UserIdInt int userId, long customFlags) {
+            String resolvedType, boolean defaultOnly, ArrayList<F[]> listCut, int userId,
+            long customFlags) {
         ArrayList<R> resultList = new ArrayList<R>();
 
         final boolean debug = localLOGV ||
                 ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
 
-        if (blockNullAction(computer, intent, resolvedType, callingUid, debug)) return resultList;
-
         FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
         final String scheme = intent.getScheme();
         int N = listCut.size();
@@ -391,26 +365,18 @@
             buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType, scheme,
                     listCut.get(i), resultList, userId, customFlags);
         }
-        filterResults(computer, intent, resultList);
+        filterResults(resultList);
         sortResults(resultList);
         return resultList;
     }
 
-    public final List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
-            String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
-        return queryIntent(snapshot, intent, resolvedType, defaultOnly,
-                Binder.getCallingUid(), userId, 0);
-    }
-
     public List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
-            String resolvedType, boolean defaultOnly, int callingUid, @UserIdInt int userId) {
-        return queryIntent(snapshot, intent, resolvedType, defaultOnly, callingUid, userId, 0);
+            String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+        return queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, 0);
     }
 
     protected final List<R> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
-            String resolvedType, boolean defaultOnly, int callingUid, @UserIdInt int userId,
-            long customFlags) {
-        final Computer computer = (Computer) snapshot;
+            String resolvedType, boolean defaultOnly, @UserIdInt int userId, long customFlags) {
         String scheme = intent.getScheme();
 
         ArrayList<R> finalList = new ArrayList<R>();
@@ -422,8 +388,6 @@
             TAG, "Resolving type=" + resolvedType + " scheme=" + scheme
             + " defaultOnly=" + defaultOnly + " userId=" + userId + " of " + intent);
 
-        if (blockNullAction(computer, intent, resolvedType, callingUid, debug)) return finalList;
-
         F[] firstTypeCut = null;
         F[] secondTypeCut = null;
         F[] thirdTypeCut = null;
@@ -484,6 +448,7 @@
         }
 
         FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
+        Computer computer = (Computer) snapshot;
         if (firstTypeCut != null) {
             buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType,
                     scheme, firstTypeCut, finalList, userId, customFlags);
@@ -500,7 +465,7 @@
             buildResolveList(computer, intent, categories, debug, defaultOnly, resolvedType,
                     scheme, schemeCut, finalList, userId, customFlags);
         }
-        filterResults(computer, intent, finalList);
+        filterResults(finalList);
         sortResults(finalList);
 
         if (debug) {
@@ -569,8 +534,7 @@
     /**
      * Apply filtering to the results. This happens before the results are sorted.
      */
-    protected void filterResults(@NonNull Computer computer, @NonNull Intent intent,
-            List<R> results) {
+    protected void filterResults(List<R> results) {
     }
 
     protected void dumpFilter(PrintWriter out, String prefix, F filter) {
@@ -802,11 +766,7 @@
                 continue;
             }
 
-            match = intentFilter.match(action, resolvedType, scheme, data, categories, TAG,
-                    false /*supportWildcards*/,
-                    false /*blockNullAction: already handled*/,
-                    null /*ignoreActions*/,
-                    null /*extras*/);
+            match = intentFilter.match(action, resolvedType, scheme, data, categories, TAG);
             if (match >= 0) {
                 if (debug) Slog.v(TAG, "  Filter matched!  match=0x" +
                         Integer.toHexString(match) + " hasDefault="
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index c16314b..225afea 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -38,6 +38,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -195,6 +196,9 @@
     private final IAccountAuthenticatorCache mAuthenticatorCache;
     private static final String PRE_N_DATABASE_NAME = "accounts.db";
     private static final Intent ACCOUNTS_CHANGED_INTENT;
+    private static final Bundle ACCOUNTS_CHANGED_OPTIONS = new BroadcastOptions()
+            .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
+            .toBundle();
 
     private static final int SIGNATURE_CHECK_MISMATCH = 0;
     private static final int SIGNATURE_CHECK_MATCH = 1;
@@ -1075,7 +1079,8 @@
         Log.i(TAG, "the accountType= " + (accountType == null ? "" : accountType)
                 + " changed with useCase=" + useCase + " for userId=" + userId
                 + ", sending broadcast of " + ACCOUNTS_CHANGED_INTENT.getAction());
-        mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
+        mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId),
+                null /* receiverPermission */, ACCOUNTS_CHANGED_OPTIONS);
     }
 
     private void sendAccountRemovedBroadcast(
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 70304c5..f90a3ce 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -137,6 +137,7 @@
 import android.app.RemoteServiceException.ForegroundServiceDidNotStartInTimeException;
 import android.app.Service;
 import android.app.ServiceStartArgs;
+import android.app.StartForegroundCalledOnStoppedServiceException;
 import android.app.admin.DevicePolicyEventLogger;
 import android.app.compat.CompatChanges;
 import android.app.usage.UsageEvents;
@@ -800,13 +801,17 @@
                     ? res.permission : "private to package");
         }
 
-
-        // TODO(short-service): This is inside startService() / startForegroundService().
-        // Consider if there's anything special we have to do if these are called on an already-
-        // running short-FGS... But given these APIs shouldn't change the FGS type, we likely
-        // don't need to do anything. (If they would change the FGS type, we'd have to stop
-        // the timeout)
         ServiceRecord r = res.record;
+        // Note, when startService() or startForegroundService() is called on an already
+        // running SHORT_SERVICE FGS, the call will succeed (i.e. we won't throw
+        // ForegroundServiceStartNotAllowedException), even when the service is alerady timed
+        // out. This is because these APIs will essnetially only change the "started" state
+        // of the service, and it won't afect "the foreground-ness" of the service, or the type
+        // of the FGS.
+        // However, this call will still _not_ extend the SHORT_SERVICE timeout either.
+        // Also, if the app tries to change the type of the FGS later (using
+        // Service.startForeground()), at that point we will consult the BFSL check and the timeout
+        // and make the necessary decisions.
         setFgsRestrictionLocked(callingPackage, callingPid, callingUid, service, r, userId,
                 backgroundStartPrivileges, false /* isBindService */);
 
@@ -2035,8 +2040,7 @@
                         // suddenly disallow it.
                         // However, this would be very problematic if used with a short-FGS, so we
                         // explicitly disallow this combination.
-                        // TODO(short-service): Change to another exception type?
-                        throw new IllegalStateException(
+                        throw new StartForegroundCalledOnStoppedServiceException(
                                 "startForeground(SHORT_SERVICE) called on a service that's not"
                                 + " started.");
                     }
@@ -2241,10 +2245,6 @@
                         cancelForegroundNotificationLocked(r);
                         r.foregroundId = id;
                     }
-
-                    // TODO(short-service): Stop the short service timeout, if the type is changing
-                    // from short to non-short. (should we do it earlier?)
-
                     notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;
                     r.foregroundNoti = notification;
                     r.foregroundServiceType = foregroundServiceType;
@@ -3190,7 +3190,7 @@
             try {
                 sr.app.getThread().scheduleTimeoutService(sr, sr.getShortFgsInfo().getStartId());
             } catch (RemoteException e) {
-                // TODO(short-service): Anything to do here?
+                Slog.w(TAG_SERVICE, "Exception from scheduleTimeoutService: " + e.toString());
             }
             // Schedule the procstate demotion timeout and ANR timeout.
             {
@@ -3262,8 +3262,9 @@
             }
             mAm.appNotResponding(sr.app, tr);
 
-            // TODO(short-service): Make sure, if the FGS stops after this, the ANR dialog
-            // disappears.
+            // TODO: Can we close the ANR dialog here, if it's still shown? Currently, the ANR
+            // dialog really doesn't remember the "cause" (especially if there have been multiple
+            // ANRs), so it's not doable.
         }
     }
 
@@ -3278,8 +3279,8 @@
         }
     }
 
-    // TODO(short-service): Hmm what is it? Should we stop the timeout here?
     private void stopServiceAndUpdateAllowlistManagerLocked(ServiceRecord service) {
+        maybeStopShortFgsTimeoutLocked(service);
         final ProcessServiceRecord psr = service.app.mServices;
         psr.stopService(service);
         psr.updateBoundClientUids();
@@ -5406,8 +5407,6 @@
 
         // Check to see if the service had been started as foreground, but being
         // brought down before actually showing a notification.  That is not allowed.
-        // TODO(short-service): This is unlikely related to short-FGS, but I'm curious why it's
-        // not allowed. Look into it.
         if (r.fgRequired) {
             Slog.w(TAG_SERVICE, "Bringing down service while still waiting for start foreground: "
                     + r);
@@ -5478,6 +5477,7 @@
         cancelForegroundNotificationLocked(r);
         final boolean exitingFg = r.isForeground;
         if (exitingFg) {
+            maybeStopShortFgsTimeoutLocked(r);
             decActiveForegroundAppLocked(smap, r);
             synchronized (mAm.mProcessStats.mLock) {
                 ServiceState stracker = r.getTracker();
@@ -5501,8 +5501,6 @@
                 mFGSLogger.logForegroundServiceStop(r.appInfo.uid, r);
             }
             mAm.updateForegroundServiceUsageStats(r.name, r.userId, false);
-
-            // TODO(short-service): Make sure we stop the timeout by here.
         }
 
         r.isForeground = false;
@@ -7822,7 +7820,7 @@
         final int callerTargetSdkVersion = r.mRecentCallerApplicationInfo != null
                 ? r.mRecentCallerApplicationInfo.targetSdkVersion : 0;
 
-        // TODO(short-service): Log BFSL too.
+        // TODO(short-service): Log the UID capabilities (for BFSL) too, and also the procstate?
         FrameworkStatsLog.write(FrameworkStatsLog.FOREGROUND_SERVICE_STATE_CHANGED,
                 r.appInfo.uid,
                 r.shortInstanceName,
@@ -7872,7 +7870,8 @@
                 r.mFgsNotificationShown ? 1 : 0,
                 durationMs,
                 r.mStartForegroundCount,
-                fgsStopReasonToString(fgsStopReason));
+                fgsStopReasonToString(fgsStopReason),
+                r.foregroundServiceType);
     }
 
     private void updateNumForegroundServicesLocked() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 74f7990..a1f7445 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -32,7 +32,6 @@
 import static android.app.ActivityManager.INSTR_FLAG_NO_RESTART;
 import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
-import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
@@ -1128,19 +1127,6 @@
         }
 
         @Override
-        protected void filterResults(@NonNull Computer computer,
-                @NonNull Intent intent, List<BroadcastFilter> results) {
-            if (intent.getAction() != null) return;
-            // When the resolved component is targeting U+, block null action intents
-            for (int i = results.size() - 1; i >= 0; --i) {
-                if (computer.isChangeEnabled(
-                        IntentFilter.BLOCK_NULL_ACTION_INTENTS, results.get(i).owningUid)) {
-                    results.remove(i);
-                }
-            }
-        }
-
-        @Override
         protected IntentFilter getIntentFilter(@NonNull BroadcastFilter input) {
             return input;
         }
@@ -3341,7 +3327,6 @@
         }
 
         mBatteryStatsService.noteProcessDied(app.info.uid, pid);
-        mOomAdjuster.updateShortFgsOwner(app.info.uid, pid, false);
 
         if (!app.isKilled()) {
             if (!fromBinderDied) {
@@ -3537,7 +3522,7 @@
 
         // We'll take the stack crawls of just the top apps using CPU.
         final int workingStatsNumber = processCpuTracker.countWorkingStats();
-        for (int i = 0; i < workingStatsNumber && extraPids.size() < 5; i++) {
+        for (int i = 0; i < workingStatsNumber && extraPids.size() < 2; i++) {
             ProcessCpuTracker.Stats stats = processCpuTracker.getWorkingStats(i);
             if (lastPids.indexOfKey(stats.pid) >= 0) {
                 if (DEBUG_ANR) {
@@ -7015,36 +7000,6 @@
     }
 
     /**
-     * Allows apps to retrieve the MIME type of a URI.
-     * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
-     * users, then it does not need permission to access the ContentProvider.
-     * Either, it needs cross-user uri grants.
-     *
-     * CTS tests for this functionality can be run with "runtest cts-appsecurity".
-     *
-     * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
-     *     src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
-     *
-     * @deprecated -- use getProviderMimeTypeAsync.
-     */
-    @Deprecated
-    @Override
-    public String getProviderMimeType(Uri uri, int userId) {
-        return mCpHelper.getProviderMimeType(uri, userId);
-    }
-
-    /**
-     * Allows apps to retrieve the MIME type of a URI.
-     * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
-     * users, then it does not need permission to access the ContentProvider.
-     * Either way, it needs cross-user uri grants.
-     */
-    @Override
-    public void getProviderMimeTypeAsync(Uri uri, int userId, RemoteCallback resultCallback) {
-        mCpHelper.getProviderMimeTypeAsync(uri, userId, resultCallback);
-    }
-
-    /**
      * Filters calls to getType based on permission. If the caller has required permission,
      * then it returns the contentProvider#getType.
      * Else, it returns the contentProvider#getTypeAnonymous, which does not
@@ -13978,19 +13933,11 @@
                         (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
                     continue;
                 }
-
-                final boolean blockNullAction = mPlatformCompat.isChangeEnabledInternal(
-                        IntentFilter.BLOCK_NULL_ACTION_INTENTS, callerApp.info);
                 // If intent has scheme "content", it will need to access
                 // provider that needs to lock mProviderMap in ActivityThread
                 // and also it may need to wait application response, so we
                 // cannot lock ActivityManagerService here.
-                if (filter.match(intent.getAction(), intent.resolveType(resolver),
-                        intent.getScheme(), intent.getData(), intent.getCategories(), TAG,
-                        false /* supportWildcards */,
-                        blockNullAction,
-                        null /* ignoreActions */,
-                        intent.getExtras()) >= 0) {
+                if (filter.match(resolver, intent, true, TAG) >= 0) {
                     if (allSticky == null) {
                         allSticky = new ArrayList<Intent>();
                     }
@@ -15009,7 +14956,7 @@
                     }
                     List<BroadcastFilter> registeredReceiversForUser =
                             mReceiverResolver.queryIntent(snapshot, intent,
-                                    resolvedType, false /*defaultOnly*/, callingUid, users[i]);
+                                    resolvedType, false /*defaultOnly*/, users[i]);
                     if (registeredReceivers == null) {
                         registeredReceivers = registeredReceiversForUser;
                     } else if (registeredReceiversForUser != null) {
@@ -15018,7 +14965,7 @@
                 }
             } else {
                 registeredReceivers = mReceiverResolver.queryIntent(snapshot, intent,
-                        resolvedType, false /*defaultOnly*/, callingUid, userId);
+                        resolvedType, false /*defaultOnly*/, userId);
             }
         }
         BroadcastQueue.traceEnd(cookie);
@@ -16353,6 +16300,7 @@
 
     // TODO(b/111541062): This method is only used for updating OOM adjustments. We need to update
     // the logic there and in mBatteryStatsService to make them aware of multiple resumed activities
+    @Nullable
     ProcessRecord getTopApp() {
         final WindowProcessController wpc = mAtmInternal != null ? mAtmInternal.getTopApp() : null;
         final ProcessRecord r = wpc != null ? (ProcessRecord) wpc.mOwner : null;
@@ -18208,8 +18156,9 @@
                     bOptions.setTemporaryAppAllowlist(mInternal.getBootTimeTempAllowListDuration(),
                             TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                             PowerExemptionManager.REASON_LOCALE_CHANGED, "");
-                    bOptions.setRemoveMatchingFilter(
-                            new IntentFilter(Intent.ACTION_LOCALE_CHANGED));
+                    bOptions.setDeliveryGroupPolicy(
+                            BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT);
+                    bOptions.setDeferUntilActive(true);
                     broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null,
                             null, null, OP_NONE, bOptions.toBundle(), false, false, MY_PID,
                             SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(),
@@ -18768,23 +18717,6 @@
         }
 
         @Override
-        public boolean canHoldWakeLocksInDeepDoze(int uid, int procstate) {
-            // This method is called with the PowerManager lock held. Do not hold AM here.
-
-            // If the procstate is high enough, it's always allowed.
-            if (procstate <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
-                return true;
-            }
-            // IF it's too low, it's not allowed.
-            if (procstate > PROCESS_STATE_IMPORTANT_FOREGROUND) {
-                return false;
-            }
-            // If it's PROCESS_STATE_IMPORTANT_FOREGROUND, then we allow it only wheen the UID
-            // has a SHORT_FGS.
-            return mOomAdjuster.hasUidShortForegroundService(uid);
-        }
-
-        @Override
         public boolean startProfileEvenWhenDisabled(@UserIdInt int userId) {
             return mUserController.startProfile(userId, /* evenWhenDisabled= */ true,
                     /* unlockListener= */ null);
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index aa9d4cc..4c1835e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -146,6 +146,7 @@
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
 
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGLConfig;
@@ -595,10 +596,14 @@
             return 1;
         }
 
-        String mimeType = intent.getType();
-        if (mimeType == null && intent.getData() != null
+        AtomicReference<String> mimeType = new AtomicReference<>(intent.getType());
+
+        if (mimeType.get() == null && intent.getData() != null
                 && "content".equals(intent.getData().getScheme())) {
-            mimeType = mInterface.getProviderMimeType(intent.getData(), mUserId);
+            mInterface.getMimeTypeFilterAsync(intent.getData(), mUserId,
+                    new RemoteCallback(result -> {
+                        mimeType.set(result.getPairValue());
+                    }));
         }
 
         do {
@@ -611,8 +616,8 @@
                     int userIdForQuery = mInternal.mUserController.handleIncomingUser(
                             Binder.getCallingPid(), Binder.getCallingUid(), mUserId, false,
                             ALLOW_NON_FULL, "ActivityManagerShellCommand", null);
-                    List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType, 0,
-                            userIdForQuery).getList();
+                    List<ResolveInfo> activities = mPm.queryIntentActivities(intent, mimeType.get(),
+                            0, userIdForQuery).getList();
                     if (activities == null || activities.size() <= 0) {
                         getErrPrintWriter().println("Error: Intent does not match any activities: "
                                 + intent);
@@ -708,12 +713,12 @@
             }
             if (mWaitOption) {
                 result = mInternal.startActivityAndWait(null, SHELL_PACKAGE_NAME, null, intent,
-                        mimeType, null, null, 0, mStartFlags, profilerInfo,
+                        mimeType.get(), null, null, 0, mStartFlags, profilerInfo,
                         options != null ? options.toBundle() : null, mUserId);
                 res = result.result;
             } else {
                 res = mInternal.startActivityAsUserWithFeature(null, SHELL_PACKAGE_NAME, null,
-                        intent, mimeType, null, null, 0, mStartFlags, profilerInfo,
+                        intent, mimeType.get(), null, null, 0, mStartFlags, profilerInfo,
                         options != null ? options.toBundle() : null, mUserId);
             }
             final long endTime = SystemClock.uptimeMillis();
@@ -3531,9 +3536,14 @@
             if (foregroundActivities) {
                 try {
                     int prcState = mIam.getUidProcessState(uid, "android");
-                    int topPid = mInternal.getTopApp().getPid();
-                    if (prcState == ProcessStateEnum.TOP && topPid == pid) {
-                        mPw.println("New foreground process: " + pid);
+                    ProcessRecord topApp = mInternal.getTopApp();
+                    if (topApp == null) {
+                        mPw.println("No top app found");
+                    } else {
+                        int topPid = topApp.getPid();
+                        if (prcState == ProcessStateEnum.TOP && topPid == pid) {
+                            mPw.println("New foreground process: " + pid);
+                        }
                     }
                     mPw.flush();
                 } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerUtils.java b/services/core/java/com/android/server/am/ActivityManagerUtils.java
index 01466b8..9be553c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerUtils.java
+++ b/services/core/java/com/android/server/am/ActivityManagerUtils.java
@@ -17,13 +17,11 @@
 
 import android.app.ActivityThread;
 import android.content.ContentResolver;
-import android.content.Intent;
 import android.provider.Settings;
 import android.util.ArrayMap;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FrameworkStatsLog;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
@@ -135,25 +133,4 @@
     public static int hashComponentNameForAtom(String shortInstanceName) {
         return getUnsignedHashUnCached(shortInstanceName) ^ getAndroidIdHash();
     }
-
-    /**
-     * Helper method to log an unsafe intent event.
-     */
-    public static void logUnsafeIntentEvent(int event, int callingUid,
-            Intent intent, String resolvedType, boolean blocked) {
-        String[] categories = intent.getCategories() == null ? new String[0]
-                : intent.getCategories().toArray(String[]::new);
-        String component = intent.getComponent() == null ? null
-                : intent.getComponent().flattenToString();
-        FrameworkStatsLog.write(FrameworkStatsLog.UNSAFE_INTENT_EVENT_REPORTED,
-                event,
-                callingUid,
-                component,
-                intent.getPackage(),
-                intent.getAction(),
-                categories,
-                resolvedType,
-                intent.getScheme(),
-                blocked);
-    }
 }
diff --git a/services/core/java/com/android/server/am/AnrHelper.java b/services/core/java/com/android/server/am/AnrHelper.java
index 463a2f8..16219cd 100644
--- a/services/core/java/com/android/server/am/AnrHelper.java
+++ b/services/core/java/com/android/server/am/AnrHelper.java
@@ -49,7 +49,7 @@
      * this time, the information might be outdated. So we only the dump the unresponsive process
      * instead of including other processes to avoid making the system more busy.
      */
-    private static final long EXPIRED_REPORT_TIME_MS = TimeUnit.MINUTES.toMillis(1);
+    private static final long EXPIRED_REPORT_TIME_MS = TimeUnit.SECONDS.toMillis(10);
 
     /**
      * If the last ANR occurred within this given time, consider it's anomaly.
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index b942f4b..841b61e 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -597,18 +597,6 @@
         final int cookie = traceBegin("enqueueBroadcast");
         r.applySingletonPolicy(mService);
 
-        final IntentFilter removeMatchingFilter = (r.options != null)
-                ? r.options.getRemoveMatchingFilter() : null;
-        if (removeMatchingFilter != null) {
-            final Predicate<Intent> removeMatching = removeMatchingFilter.asPredicate();
-            forEachMatchingBroadcast(QUEUE_PREDICATE_ANY, (testRecord, testIndex) -> {
-                // We only allow caller to remove broadcasts they enqueued
-                return (r.callingUid == testRecord.callingUid)
-                        && (r.userId == testRecord.userId)
-                        && removeMatching.test(testRecord.intent);
-            }, mBroadcastConsumerSkipAndCanceled, true);
-        }
-
         applyDeliveryGroupPolicy(r);
 
         r.enqueueTime = SystemClock.uptimeMillis();
@@ -909,6 +897,10 @@
         final IApplicationThread thread = app.getOnewayThread();
         if (thread != null) {
             try {
+                if (r.shareIdentity) {
+                    mService.mPackageManagerInt.grantImplicitAccess(r.userId, r.intent,
+                            UserHandle.getAppId(app.uid), r.callingUid, true);
+                }
                 if (receiver instanceof BroadcastFilter) {
                     notifyScheduleRegisteredReceiver(app, r, (BroadcastFilter) receiver);
                     thread.scheduleRegisteredReceiver(
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index f721d69..48df1494 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -969,122 +969,6 @@
     }
 
     /**
-     * Allows apps to retrieve the MIME type of a URI.
-     * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
-     * users, then it does not need permission to access the ContentProvider.
-     * Either, it needs cross-user uri grants.
-     *
-     * CTS tests for this functionality can be run with "runtest cts-appsecurity".
-     *
-     * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
-     *     src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
-     *
-     * @deprecated -- use getProviderMimeTypeAsync.
-     */
-    @Deprecated
-    String getProviderMimeType(Uri uri, int userId) {
-        mService.enforceNotIsolatedCaller("getProviderMimeType");
-        final String name = uri.getAuthority();
-        final int callingUid = Binder.getCallingUid();
-        final int callingPid = Binder.getCallingPid();
-        final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
-        final long ident = canClearIdentity(callingPid, callingUid, safeUserId)
-                ? Binder.clearCallingIdentity() : 0;
-        final ContentProviderHolder holder;
-        try {
-            holder = getContentProviderExternalUnchecked(name, null /* token */, callingUid,
-                    "*getmimetype*", safeUserId);
-        } finally {
-            if (ident != 0) {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-        try {
-            if (isHolderVisibleToCaller(holder, callingUid, safeUserId)) {
-                final IBinder providerConnection = holder.connection;
-                final ComponentName providerName = holder.info.getComponentName();
-                // Note: creating a new Runnable instead of using a lambda here since lambdas in
-                // java provide no guarantee that there will be a new instance returned every call.
-                // Hence, it's possible that a cached copy is returned and the ANR is executed on
-                // the incorrect provider.
-                final Runnable providerNotResponding = new Runnable() {
-                    @Override
-                    public void run() {
-                        Log.w(TAG, "Provider " + providerName + " didn't return from getType().");
-                        appNotRespondingViaProvider(providerConnection);
-                    }
-                };
-                mService.mHandler.postDelayed(providerNotResponding, 1000);
-                try {
-                    final String type = holder.provider.getType(uri);
-                    return type;
-                } finally {
-                    mService.mHandler.removeCallbacks(providerNotResponding);
-                    // We need to clear the identity to call removeContentProviderExternalUnchecked
-                    final long token = Binder.clearCallingIdentity();
-                    try {
-                        removeContentProviderExternalUnchecked(name, null /* token */, safeUserId);
-                    } finally {
-                        Binder.restoreCallingIdentity(token);
-                    }
-                }
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Content provider dead retrieving " + uri, e);
-            return null;
-        } catch (Exception e) {
-            Log.w(TAG, "Exception while determining type of " + uri, e);
-            return null;
-        }
-
-        return null;
-    }
-
-    /**
-     * Allows apps to retrieve the MIME type of a URI.
-     * If an app is in the same user as the ContentProvider, or if it is allowed to interact across
-     * users, then it does not need permission to access the ContentProvider.
-     * Either way, it needs cross-user uri grants.
-     */
-    void getProviderMimeTypeAsync(Uri uri, int userId, RemoteCallback resultCallback) {
-        mService.enforceNotIsolatedCaller("getProviderMimeTypeAsync");
-        final String name = uri.getAuthority();
-        final int callingUid = Binder.getCallingUid();
-        final int callingPid = Binder.getCallingPid();
-        final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
-        final long ident = canClearIdentity(callingPid, callingUid, safeUserId)
-                ? Binder.clearCallingIdentity() : 0;
-        final ContentProviderHolder holder;
-        try {
-            holder = getContentProviderExternalUnchecked(name, null /* token */, callingUid,
-                    "*getmimetype*", safeUserId);
-        } finally {
-            if (ident != 0) {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-
-        try {
-            if (isHolderVisibleToCaller(holder, callingUid, safeUserId)) {
-                holder.provider.getTypeAsync(uri, new RemoteCallback(result -> {
-                    final long identity = Binder.clearCallingIdentity();
-                    try {
-                        removeContentProviderExternalUnchecked(name, null, safeUserId);
-                    } finally {
-                        Binder.restoreCallingIdentity(identity);
-                    }
-                    resultCallback.sendResult(result);
-                }));
-            } else {
-                resultCallback.sendResult(Bundle.EMPTY);
-            }
-        } catch (RemoteException e) {
-            Log.w(TAG, "Content provider dead retrieving " + uri, e);
-            resultCallback.sendResult(Bundle.EMPTY);
-        }
-    }
-
-    /**
      * Filters calls to getType based on permission. If the caller has required permission,
      * then it returns the contentProvider#getType.
      * Else, it returns the contentProvider#getTypeAnonymous, which does not
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 1534ff5..50841ae 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -122,9 +122,9 @@
 30091 um_user_visibility_changed (userId|1|5),(visible|1)
 
 # Foreground service start/stop events.
-30100 am_foreground_service_start (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3)
-30101 am_foreground_service_denied (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3)
-30102 am_foreground_service_stop (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3)
+30100 am_foreground_service_start (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3),(fgsType|1)
+30101 am_foreground_service_denied (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3),(fgsType|1)
+30102 am_foreground_service_stop (User|1|5),(Component Name|3),(allowWhileInUse|1),(startReasonCode|3),(targetSdk|1|1),(callerTargetSdk|1|1),(notificationWasDeferred|1),(notificationShown|1),(durationMs|1|3),(startForegroundCount|1|1),(stopReason|3),(fgsType|1)
 
 # Intent Sender redirect for UserHandle.USER_CURRENT
 30110 am_intent_sender_redirect_user (userId|1|5)
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 0c36626..679cf0a 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -127,7 +127,6 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
-import android.util.SparseSetArray;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.CompositeRWLock;
@@ -207,7 +206,8 @@
                 return AppProtoEnums.OOM_ADJ_REASON_PROCESS_BEGIN;
             case OOM_ADJ_REASON_PROCESS_END:
                 return AppProtoEnums.OOM_ADJ_REASON_PROCESS_END;
-            case OOM_ADJ_REASON_SHORT_FGS_TIMEOUT: // TODO(short-service) add value to AppProtoEnums
+            case OOM_ADJ_REASON_SHORT_FGS_TIMEOUT:
+                return AppProtoEnums.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT;
             default:
                 return AppProtoEnums.OOM_ADJ_REASON_UNKNOWN_TO_PROTO;
         }
@@ -366,19 +366,6 @@
     @GuardedBy("mService")
     private boolean mPendingFullOomAdjUpdate = false;
 
-    /**
-     * PIDs that has a SHORT_SERVICE. We need to access it with the PowerManager lock held,
-     * so we use a fine-grained lock here.
-     */
-    @GuardedBy("mPidsWithShortFgs")
-    private final ArraySet<Integer> mPidsWithShortFgs = new ArraySet<>();
-
-    /**
-     * UIDs -> PIDs map, used with mPidsWithShortFgs.
-     */
-    @GuardedBy("mPidsWithShortFgs")
-    private final SparseSetArray<Integer> mUidsToPidsWithShortFgs = new SparseSetArray<>();
-
     /** Overrideable by a test */
     @VisibleForTesting
     protected boolean isChangeEnabled(@CachedCompatChangeId int cachedCompatChangeId,
@@ -1955,7 +1942,6 @@
                 }
             }
         }
-        updateShortFgsOwner(psr.mApp.uid, psr.mApp.mPid, hasShortForegroundServices);
 
         // If the app was recently in the foreground and moved to a foreground service status,
         // allow it to get a higher rank in memory for some time, compared to other foreground
@@ -2184,8 +2170,6 @@
                 }
             }
 
-            // TODO(short-service): While-in-user permissions. Do we need any change here for
-            // short-FGS? (Likely not)
             if (s.isForeground) {
                 final int fgsType = s.foregroundServiceType;
                 if (s.mAllowWhileInUsePermissionInFgs) {
@@ -3467,40 +3451,4 @@
             mCachedAppOptimizer.unfreezeAppLSP(app, oomAdjReason);
         }
     }
-
-    /**
-     * Update {@link #mPidsWithShortFgs} and {@link #mUidsToPidsWithShortFgs} to keep track
-     * of which UID/PID has a short FGS.
-     *
-     * TODO(short-FGS): Remove it and all the relevant code once SHORT_FGS use the FGS procstate.
-     */
-    void updateShortFgsOwner(int uid, int pid, boolean add) {
-        synchronized (mPidsWithShortFgs) {
-            if (add) {
-                mUidsToPidsWithShortFgs.add(uid, pid);
-                mPidsWithShortFgs.add(pid);
-            } else {
-                mUidsToPidsWithShortFgs.remove(uid, pid);
-                mPidsWithShortFgs.remove(pid);
-            }
-        }
-    }
-
-    /**
-     * Whether a UID has a (non-timed-out) short FGS or not.
-     * It's indirectly called by PowerManager, so we can't hold the AM lock in it.
-     */
-    boolean hasUidShortForegroundService(int uid) {
-        synchronized (mPidsWithShortFgs) {
-            final ArraySet<Integer> pids = mUidsToPidsWithShortFgs.get(uid);
-            if (pids == null || pids.size() == 0) {
-                return false;
-            }
-            for (int i = pids.size() - 1; i >= 0; i--) {
-                final int pid = pids.valueAt(i);
-                return mPidsWithShortFgs.contains(pid);
-            }
-        }
-        return false;
-    }
 }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index f4e2b0f..35f71f7 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -3100,9 +3100,10 @@
                 hostingRecord.getDefiningUid(), hostingRecord.getDefiningProcessName());
         final ProcessStateRecord state = r.mState;
 
-        if (!mService.mBooted && !mService.mBooting
+        if (!isolated && !isSdkSandbox
                 && userId == UserHandle.USER_SYSTEM
-                && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
+                && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK
+                && (TextUtils.equals(proc, info.processName))) {
             // The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
             state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
             state.setSetSchedGroup(ProcessList.SCHED_GROUP_DEFAULT);
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index c6a8bcd..d4bcd9e 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -106,9 +106,7 @@
         { "exclude-annotation": "androidx.test.filters.FlakyTest" },
         { "exclude-annotation": "org.junit.Ignore" }
       ]
-    }
-  ],
-  "presubmit-large": [
+    },
     {
       "name": "CtsUsageStatsTestCases",
       "file_patterns": [
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 88c0c7f..0d0e576 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1315,7 +1315,7 @@
         // persistent data
         initVolumeGroupStates();
 
-        mSoundDoseHelper.initSafeUsbMediaVolumeIndex();
+        mSoundDoseHelper.initSafeMediaVolumeIndex();
         // Link VGS on VSS
         initVolumeStreamStates();
 
@@ -8358,6 +8358,7 @@
             synchronized (VolumeStreamState.class) {
                 // apply device specific volumes first
                 int index;
+                boolean isAbsoluteVolume = false;
                 for (int i = 0; i < mIndexMap.size(); i++) {
                     final int device = mIndexMap.keyAt(i);
                     if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
@@ -8366,6 +8367,7 @@
                         } else if (isAbsoluteVolumeDevice(device)
                                 || isA2dpAbsoluteVolumeDevice(device)
                                 || AudioSystem.isLeAudioDeviceType(device)) {
+                            isAbsoluteVolume = true;
                             index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10);
                         } else if (isFullVolumeDevice(device)) {
                             index = (mIndexMax + 5)/10;
@@ -8374,6 +8376,11 @@
                         } else {
                             index = (mIndexMap.valueAt(i) + 5)/10;
                         }
+
+                        sendMsg(mAudioHandler, SoundDoseHelper.MSG_CSD_UPDATE_ATTENUATION,
+                                SENDMSG_REPLACE, device,  isAbsoluteVolume ? 1 : 0, this,
+                                /*delay=*/0);
+
                         setStreamVolumeIndex(index, device);
                     }
                 }
@@ -8830,7 +8837,7 @@
         final VolumeStreamState streamState = mStreamStates[update.mStreamType];
         if (update.hasVolumeIndex()) {
             int index = update.getVolumeIndex();
-            if (!mSoundDoseHelper.checkSafeMediaVolume(update.mStreamType, index, update.mDevice)) {
+            if (mSoundDoseHelper.checkSafeMediaVolume(update.mStreamType, index, update.mDevice)) {
                 index = mSoundDoseHelper.safeMediaVolumeIndex(update.mDevice);
             }
             streamState.setIndex(index, update.mDevice, update.mCaller,
@@ -8848,6 +8855,10 @@
     /*package*/ void setDeviceVolume(VolumeStreamState streamState, int device) {
 
         synchronized (VolumeStreamState.class) {
+            sendMsg(mAudioHandler, SoundDoseHelper.MSG_CSD_UPDATE_ATTENUATION, SENDMSG_REPLACE,
+                    device, (isAbsoluteVolumeDevice(device) || isA2dpAbsoluteVolumeDevice(device)
+                            || AudioSystem.isLeAudioDeviceType(device) ? 1 : 0),
+                    streamState, /*delay=*/0);
             // Apply volume
             streamState.applyDeviceVolume_syncVSS(device);
 
diff --git a/services/core/java/com/android/server/audio/SoundDoseHelper.java b/services/core/java/com/android/server/audio/SoundDoseHelper.java
index 4e8e704..cf81dbe 100644
--- a/services/core/java/com/android/server/audio/SoundDoseHelper.java
+++ b/services/core/java/com/android/server/audio/SoundDoseHelper.java
@@ -52,10 +52,10 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Objects;
-import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 /**
@@ -79,7 +79,6 @@
     // 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
@@ -89,9 +88,12 @@
     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;
+    /*package*/ static final int MSG_CSD_UPDATE_ATTENUATION = SAFE_MEDIA_VOLUME_MSG_START + 5;
 
     private static final int UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX = (20 * 3600 * 1000); // 20 hours
 
+    private static final int MOMENTARY_EXPOSURE_TIMEOUT_MS = (20 * 3600 * 1000); // 20 hours
+
     // 30s after boot completed
     private static final int SAFE_VOLUME_CONFIGURE_TIMEOUT_MS = 30000;
 
@@ -125,23 +127,50 @@
 
     // mSafeMediaVolumeIndex is the cached value of config_safe_media_volume_index property
     private int mSafeMediaVolumeIndex;
-    // mSafeUsbMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
+    // mSafeMediaVolumeDbfs is the cached value of the config_safe_media_volume_usb_mB
     // property, divided by 100.0.
-    private float mSafeUsbMediaVolumeDbfs;
+    // For now using the same value for CSD supported devices
+    private float mSafeMediaVolumeDbfs;
 
-    // mSafeUsbMediaVolumeIndex is used for USB Headsets and is the music volume UI index
-    // corresponding to a gain of mSafeUsbMediaVolumeDbfs (defaulting to -37dB) in audio
-    // flinger mixer.
-    // We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
-    // amplification when both effects are on with all band gains at maximum.
-    // This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
-    // the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
-    private int mSafeUsbMediaVolumeIndex;
-    // mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced,
-    private final Set<Integer> mSafeMediaVolumeDevices = new HashSet<>(
-            Arrays.asList(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
-                    AudioSystem.DEVICE_OUT_WIRED_HEADPHONE, AudioSystem.DEVICE_OUT_USB_HEADSET));
+    private static class SafeDeviceVolumeInfo {
+        int mDeviceType;
+        int mSafeVolumeIndex = -1;
 
+        SafeDeviceVolumeInfo(int deviceType) {
+            mDeviceType = deviceType;
+        }
+    }
+
+    /**
+     * mSafeMediaVolumeDevices lists the devices for which safe media volume is enforced.
+     * Contains a safe volume index for a given device type.
+     * Indexes are used for headsets and is the music volume UI index
+     * corresponding to a gain of mSafeMediaVolumeDbfs (defaulting to -37dB) in audio
+     * flinger mixer.
+     * We remove -22 dBs from the theoretical -15dB to account for the EQ + bass boost
+     * amplification when both effects are on with all band gains at maximum.
+     * This level corresponds to a loudness of 85 dB SPL for the warning to be displayed when
+     * the headset is compliant to EN 60950 with a max loudness of 100dB SPL.
+     */
+    private final HashMap<Integer, SafeDeviceVolumeInfo> mSafeMediaVolumeDevices =
+            new HashMap<>() {{
+                put(AudioSystem.DEVICE_OUT_WIRED_HEADSET,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_WIRED_HEADSET));
+                put(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_WIRED_HEADPHONE));
+                put(AudioSystem.DEVICE_OUT_USB_HEADSET,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_USB_HEADSET));
+                put(AudioSystem.DEVICE_OUT_BLE_HEADSET,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLE_HEADSET));
+                put(AudioSystem.DEVICE_OUT_BLE_BROADCAST,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLE_BROADCAST));
+                put(AudioSystem.DEVICE_OUT_HEARING_AID,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_HEARING_AID));
+                put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES));
+                put(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+                        new SafeDeviceVolumeInfo(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
+            }};
 
     // mMusicActiveMs is the cumulative time of music activity since safe volume was disabled.
     // When this time reaches UNSAFE_VOLUME_MUSIC_ACTIVE_MS_MAX, the safe media volume is re-enabled
@@ -158,12 +187,16 @@
 
     private final boolean mEnableCsd;
 
-    private ISoundDose mSoundDose;
-
     private final Object mCsdStateLock = new Object();
 
+    private final AtomicReference<ISoundDose> mSoundDose = new AtomicReference<>();
+
     @GuardedBy("mCsdStateLock")
     private float mCurrentCsd = 0.f;
+
+    @GuardedBy("mCsdStateLock")
+    private long mLastMomentaryExposureTimeMs = -1;
+
     // dose at which the next dose reached warning occurs
     @GuardedBy("mCsdStateLock")
     private float mNextCsdWarning = 1.0f;
@@ -179,10 +212,26 @@
 
     private final ISoundDoseCallback.Stub mSoundDoseCallback = new ISoundDoseCallback.Stub() {
         public void onMomentaryExposure(float currentMel, int deviceId) {
+            if (!mEnableCsd) {
+                Log.w(TAG, "onMomentaryExposure: csd not supported, ignoring callback");
+                return;
+            }
+
             Log.w(TAG, "DeviceId " + deviceId + " triggered momentary exposure with value: "
                     + currentMel);
             mLogger.enqueue(SoundDoseEvent.getMomentaryExposureEvent(currentMel));
-            if (mEnableCsd) {
+
+            boolean postWarning = false;
+            synchronized (mCsdStateLock) {
+                if (mLastMomentaryExposureTimeMs < 0
+                        || (System.currentTimeMillis() - mLastMomentaryExposureTimeMs)
+                        >= MOMENTARY_EXPOSURE_TIMEOUT_MS) {
+                    mLastMomentaryExposureTimeMs = System.currentTimeMillis();
+                    postWarning = true;
+                }
+            }
+
+            if (postWarning) {
                 mVolumeController.postDisplayCsdWarning(
                         AudioManager.CSD_WARNING_MOMENTARY_EXPOSURE,
                         getTimeoutMsForWarning(AudioManager.CSD_WARNING_MOMENTARY_EXPOSURE));
@@ -241,12 +290,10 @@
         mContext = context;
 
         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);
-        }
+        initCsd();
+
+        mSafeMediaVolumeState = mSettings.getGlobalInt(audioService.getContentResolver(),
+                Settings.Global.AUDIO_SAFE_VOLUME_STATE, SAFE_MEDIA_VOLUME_NOT_CONFIGURED);
 
         // The default safe volume index read here will be replaced by the actual value when
         // the mcc is read by onConfigureSafeMedia()
@@ -263,9 +310,14 @@
             return 0.f;
         }
 
-        Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+        final ISoundDose soundDose = mSoundDose.get();
+        if (soundDose == null) {
+            Log.w(TAG, "Sound dose interface not initialized");
+            return 0.f;
+        }
+
         try {
-            return mSoundDose.getOutputRs2();
+            return soundDose.getOutputRs2();
         } catch (RemoteException e) {
             Log.e(TAG, "Exception while getting the RS2 exposure value", e);
             return 0.f;
@@ -277,9 +329,14 @@
             return;
         }
 
-        Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+        final ISoundDose soundDose = mSoundDose.get();
+        if (soundDose == null) {
+            Log.w(TAG, "Sound dose interface not initialized");
+            return;
+        }
+
         try {
-            mSoundDose.setOutputRs2(rs2Value);
+            soundDose.setOutputRs2(rs2Value);
         } catch (RemoteException e) {
             Log.e(TAG, "Exception while setting the RS2 exposure value", e);
         }
@@ -290,9 +347,14 @@
             return -1.f;
         }
 
-        Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+        final ISoundDose soundDose = mSoundDose.get();
+        if (soundDose == null) {
+            Log.w(TAG, "Sound dose interface not initialized");
+            return -1.f;
+        }
+
         try {
-            return mSoundDose.getCsd();
+            return soundDose.getCsd();
         } catch (RemoteException e) {
             Log.e(TAG, "Exception while getting the CSD value", e);
             return -1.f;
@@ -304,13 +366,18 @@
             return;
         }
 
-        Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+        final ISoundDose soundDose = mSoundDose.get();
+        if (soundDose == null) {
+            Log.w(TAG, "Sound dose interface not initialized");
+            return;
+        }
+
         try {
             final SoundDoseRecord record = new SoundDoseRecord();
             record.timestamp = System.currentTimeMillis();
             record.value = csd;
             final SoundDoseRecord[] recordArray = new SoundDoseRecord[] { record };
-            mSoundDose.resetCsd(csd, recordArray);
+            soundDose.resetCsd(csd, recordArray);
         } catch (RemoteException e) {
             Log.e(TAG, "Exception while setting the CSD value", e);
         }
@@ -321,9 +388,14 @@
             return;
         }
 
-        Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+        final ISoundDose soundDose = mSoundDose.get();
+        if (soundDose == null) {
+            Log.w(TAG, "Sound dose interface not initialized");
+            return;
+        }
+
         try {
-            mSoundDose.forceUseFrameworkMel(useFrameworkMel);
+            soundDose.forceUseFrameworkMel(useFrameworkMel);
         } catch (RemoteException e) {
             Log.e(TAG, "Exception while forcing the internal MEL computation", e);
         }
@@ -334,9 +406,14 @@
             return;
         }
 
-        Objects.requireNonNull(mSoundDose, "Sound dose interface not initialized");
+        final ISoundDose soundDose = mSoundDose.get();
+        if (soundDose == null) {
+            Log.w(TAG, "Sound dose interface not initialized");
+            return;
+        }
+
         try {
-            mSoundDose.forceComputeCsdOnAllDevices(computeCsdOnAllDevices);
+            soundDose.forceComputeCsdOnAllDevices(computeCsdOnAllDevices);
         } catch (RemoteException e) {
             Log.e(TAG, "Exception while forcing CSD computation on all devices", e);
         }
@@ -347,14 +424,12 @@
     }
 
     /*package*/ int safeMediaVolumeIndex(int device) {
-        if (!mSafeMediaVolumeDevices.contains(device)) {
+        final SafeDeviceVolumeInfo vi = mSafeMediaVolumeDevices.get(device);
+        if (vi == null) {
             return MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
         }
-        if (device == AudioSystem.DEVICE_OUT_USB_HEADSET) {
-            return mSafeUsbMediaVolumeIndex;
-        } else {
-            return mSafeMediaVolumeIndex;
-        }
+
+        return vi.mSafeVolumeIndex;
     }
 
     /*package*/ void restoreMusicActiveMs() {
@@ -378,20 +453,24 @@
     /*package*/ void enforceSafeMediaVolume(String caller) {
         AudioService.VolumeStreamState streamState = mAudioService.getVssVolumeForStream(
                 AudioSystem.STREAM_MUSIC);
-        Set<Integer> devices = mSafeMediaVolumeDevices;
 
-        for (int device : devices) {
-            int index = streamState.getIndex(device);
-            int safeIndex = safeMediaVolumeIndex(device);
+        for (SafeDeviceVolumeInfo vi : mSafeMediaVolumeDevices.values()) {
+            int index = streamState.getIndex(vi.mDeviceType);
+            int safeIndex = safeMediaVolumeIndex(vi.mDeviceType);
             if (index > safeIndex) {
-                streamState.setIndex(safeIndex, device, caller, true /*hasModifyAudioSettings*/);
+                streamState.setIndex(safeIndex, vi.mDeviceType, caller,
+                        true /*hasModifyAudioSettings*/);
                 mAudioHandler.sendMessageAtTime(
-                        mAudioHandler.obtainMessage(MSG_SET_DEVICE_VOLUME, device, /*arg2=*/0,
-                                streamState), /*delay=*/0);
+                        mAudioHandler.obtainMessage(MSG_SET_DEVICE_VOLUME, vi.mDeviceType,
+                                /*arg2=*/0, streamState), /*delay=*/0);
             }
         }
     }
 
+    /**
+     * Returns {@code true} if the safe media actions can be applied for the given stream type,
+     * volume index and device.
+     **/
     /*package*/ boolean checkSafeMediaVolume(int streamType, int index, int device) {
         boolean result;
         synchronized (mSafeMediaVolumeStateLock) {
@@ -402,17 +481,16 @@
 
     @GuardedBy("mSafeMediaVolumeStateLock")
     private boolean checkSafeMediaVolume_l(int streamType, int index, int device) {
-        return (mSafeMediaVolumeState != SAFE_MEDIA_VOLUME_ACTIVE)
-                    || (AudioService.mStreamVolumeAlias[streamType] != AudioSystem.STREAM_MUSIC)
-                    || (!mSafeMediaVolumeDevices.contains(device))
-                    || (index <= safeMediaVolumeIndex(device))
-                    || mEnableCsd;
+        return (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE)
+                    && (AudioService.mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC)
+                    && (mSafeMediaVolumeDevices.containsKey(device))
+                    && (index > safeMediaVolumeIndex(device));
     }
 
     /*package*/ boolean willDisplayWarningAfterCheckVolume(int streamType, int index, int device,
             int flags) {
         synchronized (mSafeMediaVolumeStateLock) {
-            if (!checkSafeMediaVolume_l(streamType, index, device)) {
+            if (checkSafeMediaVolume_l(streamType, index, device)) {
                 mVolumeController.postDisplaySafeVolumeWarning(flags);
                 mPendingVolumeCommand = new StreamVolumeCommand(
                         streamType, index, flags, device);
@@ -443,15 +521,13 @@
     /*package*/ void scheduleMusicActiveCheck() {
         synchronized (mSafeMediaVolumeStateLock) {
             cancelMusicActiveCheck();
-            if (!mEnableCsd) {
-                mMusicActiveIntent = PendingIntent.getBroadcast(mContext,
-                        REQUEST_CODE_CHECK_MUSIC_ACTIVE,
-                        new Intent(ACTION_CHECK_MUSIC_ACTIVE),
-                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
-                mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
-                        SystemClock.elapsedRealtime()
-                                + MUSIC_ACTIVE_POLL_PERIOD_MS, mMusicActiveIntent);
-            }
+            mMusicActiveIntent = PendingIntent.getBroadcast(mContext,
+                    REQUEST_CODE_CHECK_MUSIC_ACTIVE,
+                    new Intent(ACTION_CHECK_MUSIC_ACTIVE),
+                    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+            mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                    SystemClock.elapsedRealtime()
+                            + MUSIC_ACTIVE_POLL_PERIOD_MS, mMusicActiveIntent);
         }
     }
 
@@ -459,7 +535,7 @@
         synchronized (mSafeMediaVolumeStateLock) {
             if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_INACTIVE) {
                 int device = mAudioService.getDeviceForStream(AudioSystem.STREAM_MUSIC);
-                if (mSafeMediaVolumeDevices.contains(device) && isStreamActive) {
+                if (mSafeMediaVolumeDevices.containsKey(device) && isStreamActive) {
                     scheduleMusicActiveCheck();
                     int index = mAudioService.getVssVolumeForDevice(AudioSystem.STREAM_MUSIC,
                             device);
@@ -487,27 +563,31 @@
 
     /*package*/ void configureSafeMedia(boolean forced, String caller) {
         int msg = MSG_CONFIGURE_SAFE_MEDIA;
-        mAudioHandler.removeMessages(msg);
+        if (forced) {
+            // unforced should not cancel forced configure messages
+            mAudioHandler.removeMessages(msg);
+        }
 
         long time = 0;
         if (forced) {
             time = (SystemClock.uptimeMillis() + (SystemProperties.getBoolean(
                     "audio.safemedia.bypass", false) ? 0 : SAFE_VOLUME_CONFIGURE_TIMEOUT_MS));
         }
+
         mAudioHandler.sendMessageAtTime(
                 mAudioHandler.obtainMessage(msg, /*arg1=*/forced ? 1 : 0, /*arg2=*/0, caller),
                 time);
     }
 
-    /*package*/ void initSafeUsbMediaVolumeIndex() {
-        // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
-        // relies on audio policy having correct ranges for volume indexes.
-        mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
+    /*package*/ void initSafeMediaVolumeIndex() {
+        for (SafeDeviceVolumeInfo vi : mSafeMediaVolumeDevices.values()) {
+            vi.mSafeVolumeIndex = getSafeDeviceMediaVolumeIndex(vi.mDeviceType);
+        }
     }
 
     /*package*/ int getSafeMediaVolumeIndex(int device) {
-        if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE && mSafeMediaVolumeDevices.contains(
-                device)) {
+        if (mSafeMediaVolumeState == SAFE_MEDIA_VOLUME_ACTIVE
+                && mSafeMediaVolumeDevices.containsKey(device)) {
             return safeMediaVolumeIndex(device);
         } else {
             return -1;
@@ -516,7 +596,7 @@
 
     /*package*/ boolean raiseVolumeDisplaySafeMediaVolume(int streamType, int index, int device,
             int flags) {
-        if (checkSafeMediaVolume(streamType, index, device)) {
+        if (!checkSafeMediaVolume(streamType, index, device)) {
             return false;
         }
 
@@ -525,7 +605,7 @@
     }
 
     /*package*/ boolean safeDevicesContains(int device) {
-        return mSafeMediaVolumeDevices.contains(device);
+        return mSafeMediaVolumeDevices.containsKey(device);
     }
 
     /*package*/ void invalidatPendingVolumeCommand() {
@@ -551,6 +631,15 @@
             case MSG_PERSIST_CSD_VALUES:
                 onPersistSoundDoseRecords();
                 break;
+            case MSG_CSD_UPDATE_ATTENUATION:
+                final int device = msg.arg1;
+                final boolean isAbsoluteVolume = (msg.arg2 == 1);
+                final AudioService.VolumeStreamState streamState =
+                        (AudioService.VolumeStreamState) msg.obj;
+
+                updateDoseAttenuation(streamState.getIndex(device), device,
+                        streamState.getStreamType(), isAbsoluteVolume);
+                break;
             default:
                 Log.e(TAG, "Unexpected msg to handle: " + msg.what);
                 break;
@@ -562,8 +651,11 @@
         pw.print("  mSafeMediaVolumeState=");
         pw.println(safeMediaVolumeStateToString(mSafeMediaVolumeState));
         pw.print("  mSafeMediaVolumeIndex="); pw.println(mSafeMediaVolumeIndex);
-        pw.print("  mSafeUsbMediaVolumeIndex="); pw.println(mSafeUsbMediaVolumeIndex);
-        pw.print("  mSafeUsbMediaVolumeDbfs="); pw.println(mSafeUsbMediaVolumeDbfs);
+        for (SafeDeviceVolumeInfo vi : mSafeMediaVolumeDevices.values()) {
+            pw.print("  mSafeMediaVolumeIndex["); pw.print(vi.mDeviceType);
+            pw.print("]="); pw.println(vi.mSafeVolumeIndex);
+        }
+        pw.print("  mSafeMediaVolumeDbfs="); pw.println(mSafeMediaVolumeDbfs);
         pw.print("  mMusicActiveMs="); pw.println(mMusicActiveMs);
         pw.print("  mMcc="); pw.println(mMcc);
         pw.print("  mPendingVolumeCommand="); pw.println(mPendingVolumeCommand);
@@ -574,16 +666,18 @@
 
     /*package*/void reset() {
         Log.d(TAG, "Reset the sound dose helper");
-        mSoundDose = AudioSystem.getSoundDoseInterface(mSoundDoseCallback);
+        mSoundDose.set(AudioSystem.getSoundDoseInterface(mSoundDoseCallback));
+
         synchronized (mCsdStateLock) {
             try {
-                if (mSoundDose != null && mSoundDose.asBinder().isBinderAlive()) {
+                final ISoundDose soundDose = mSoundDose.get();
+                if (soundDose != null && soundDose.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);
+                        soundDose.resetCsd(mCurrentCsd, records);
                     }
                 }
             } catch (RemoteException e) {
@@ -592,36 +686,71 @@
         }
     }
 
-    private void initCsd() {
-        if (mEnableCsd) {
-            Log.v(TAG, "Initializing sound dose");
+    private void updateDoseAttenuation(int newIndex, int device, int streamType,
+            boolean isAbsoluteVolume) {
+        if (!mEnableCsd) {
+            return;
+        }
 
-            synchronized (mCsdStateLock) {
-                if (mGlobalTimeOffsetInSecs == GLOBAL_TIME_OFFSET_UNINITIALIZED) {
-                    mGlobalTimeOffsetInSecs = System.currentTimeMillis() / 1000L;
-                }
+        final ISoundDose soundDose = mSoundDose.get();
+        if (soundDose == null) {
+            Log.w(TAG,  "Can not apply attenuation. ISoundDose itf is null.");
+            return;
+        }
 
-                float prevCsd = mCurrentCsd;
-                // Restore persisted values
-                mCurrentCsd = parseGlobalSettingFloat(
-                        Settings.Global.AUDIO_SAFE_CSD_CURRENT_VALUE, /* defaultValue= */0.f);
-                if (mCurrentCsd != prevCsd) {
-                    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),
-                            mGlobalTimeOffsetInSecs);
-                    if (records != null) {
-                        mDoseRecords.addAll(records);
-                    }
-                }
+        try {
+            if (!isAbsoluteVolume) {
+                // remove any possible previous attenuation
+                soundDose.updateAttenuation(/* attenuationDB= */0.f, device);
+
+                return;
             }
 
-            reset();
+            if (AudioService.mStreamVolumeAlias[streamType] == AudioSystem.STREAM_MUSIC
+                    && mSafeMediaVolumeDevices.containsKey(device)) {
+                soundDose.updateAttenuation(
+                        AudioSystem.getStreamVolumeDB(AudioSystem.STREAM_MUSIC,
+                                (newIndex + 5) / 10,
+                                device), device);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not apply the attenuation for MEL calculation with volume index "
+                    + newIndex, e);
         }
     }
 
+    private void initCsd() {
+        if (!mEnableCsd) {
+            return;
+        }
+
+        Log.v(TAG, "Initializing sound dose");
+
+        synchronized (mCsdStateLock) {
+            if (mGlobalTimeOffsetInSecs == GLOBAL_TIME_OFFSET_UNINITIALIZED) {
+                mGlobalTimeOffsetInSecs = System.currentTimeMillis() / 1000L;
+            }
+
+            float prevCsd = mCurrentCsd;
+            // Restore persisted values
+            mCurrentCsd = parseGlobalSettingFloat(
+                    Settings.Global.AUDIO_SAFE_CSD_CURRENT_VALUE, /* defaultValue= */0.f);
+            if (mCurrentCsd != prevCsd) {
+                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),
+                        mGlobalTimeOffsetInSecs);
+                if (records != null) {
+                    mDoseRecords.addAll(records);
+                }
+            }
+        }
+
+        reset();
+    }
+
     private void onConfigureSafeMedia(boolean force, String caller) {
         synchronized (mSafeMediaVolumeStateLock) {
             int mcc = mContext.getResources().getConfiguration().mcc;
@@ -629,7 +758,7 @@
                 mSafeMediaVolumeIndex = mContext.getResources().getInteger(
                         com.android.internal.R.integer.config_safe_media_volume_index) * 10;
 
-                mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
+                initSafeMediaVolumeIndex();
 
                 boolean safeMediaVolumeEnabled =
                         SystemProperties.getBoolean("audio.safemedia.force", false)
@@ -642,7 +771,7 @@
                 // The persisted state is either "disabled" or "active": this is the state applied
                 // next time we boot and cannot be "inactive"
                 int persistedState;
-                if (safeMediaVolumeEnabled && !safeMediaVolumeBypass && !mEnableCsd) {
+                if (safeMediaVolumeEnabled && !safeMediaVolumeBypass) {
                     persistedState = SAFE_MEDIA_VOLUME_ACTIVE;
                     // The state can already be "inactive" here if the user has forced it before
                     // the 30 seconds timeout for forced configuration. In this case we don't reset
@@ -668,10 +797,6 @@
                                 /*obj=*/null), /*delay=*/0);
             }
         }
-
-        if (mEnableCsd) {
-            initCsd();
-        }
     }
 
     private int getTimeoutMsForWarning(@AudioManager.CsdWarning int csdWarning) {
@@ -719,25 +844,32 @@
         mAudioHandler.obtainMessage(MSG_PERSIST_MUSIC_ACTIVE_MS, mMusicActiveMs, 0).sendToTarget();
     }
 
-    private int getSafeUsbMediaVolumeIndex() {
+    private int getSafeDeviceMediaVolumeIndex(int deviceType) {
+        // legacy implementation uses mSafeMediaVolumeIndex for wired HS/HP
+        // instead of computing it from the volume curves
+        if ((deviceType == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE
+                || deviceType == AudioSystem.DEVICE_OUT_WIRED_HEADSET) && !mEnableCsd) {
+            return mSafeMediaVolumeIndex;
+        }
+
         // determine UI volume index corresponding to the wanted safe gain in dBFS
         int min = MIN_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
         int max = MAX_STREAM_VOLUME[AudioSystem.STREAM_MUSIC];
 
-        mSafeUsbMediaVolumeDbfs = mContext.getResources().getInteger(
+        mSafeMediaVolumeDbfs = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_safe_media_volume_usb_mB) / 100.0f;
 
         while (Math.abs(max - min) > 1) {
             int index = (max + min) / 2;
-            float gainDB = AudioSystem.getStreamVolumeDB(
-                    AudioSystem.STREAM_MUSIC, index, AudioSystem.DEVICE_OUT_USB_HEADSET);
+            float gainDB = AudioSystem.getStreamVolumeDB(AudioSystem.STREAM_MUSIC, index,
+                    deviceType);
             if (Float.isNaN(gainDB)) {
                 //keep last min in case of read error
                 break;
-            } else if (gainDB == mSafeUsbMediaVolumeDbfs) {
+            } else if (gainDB == mSafeMediaVolumeDbfs) {
                 min = index;
                 break;
-            } else if (gainDB < mSafeUsbMediaVolumeDbfs) {
+            } else if (gainDB < mSafeMediaVolumeDbfs) {
                 min = index;
             } else {
                 max = index;
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index cdf22aa..69ad152 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -64,7 +64,6 @@
     private final ArrayList<UserTemplate> mUnknownHALTemplates = new ArrayList<>();
     private final BiometricUtils<S> mBiometricUtils;
     private final Map<Integer, Long> mAuthenticatorIds;
-    private final List<S> mEnrolledList;
     private final boolean mHasEnrollmentsBeforeStarting;
     private BaseClientMonitor mCurrentTask;
     private boolean mFavorHalEnrollments = false;
@@ -135,13 +134,12 @@
     protected InternalCleanupClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
             int userId, @NonNull String owner, int sensorId,
             @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            @NonNull List<S> enrolledList, @NonNull BiometricUtils<S> utils,
+            @NonNull BiometricUtils<S> utils,
             @NonNull Map<Integer, Long> authenticatorIds) {
         super(context, lazyDaemon, null /* token */, null /* ClientMonitorCallbackConverter */,
                 userId, owner, 0 /* cookie */, sensorId, logger, biometricContext);
         mBiometricUtils = utils;
         mAuthenticatorIds = authenticatorIds;
-        mEnrolledList = enrolledList;
         mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty();
     }
 
@@ -169,12 +167,16 @@
     public void start(@NonNull ClientMonitorCallback callback) {
         super.start(callback);
 
+        final List<S> enrolledList =
+                mBiometricUtils.getBiometricsForUser(getContext(), getTargetUserId());
+
         // Start enumeration. Removal will start if necessary, when enumeration is completed.
         mCurrentTask = getEnumerateClient(getContext(), mLazyDaemon, getToken(), getTargetUserId(),
-                getOwnerString(), mEnrolledList, mBiometricUtils, getSensorId(), getLogger(),
+                getOwnerString(), enrolledList, mBiometricUtils, getSensorId(), getLogger(),
                 getBiometricContext());
 
-        Slog.d(TAG, "Starting enumerate: " + mCurrentTask);
+        Slog.d(TAG, "Starting enumerate: " + mCurrentTask + " enrolledList size:"
+                + enrolledList.size());
         mCurrentTask.start(mEnumerateCallback);
     }
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
index b0b23fa..f09d192 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
@@ -43,10 +43,10 @@
     FaceInternalCleanupClient(@NonNull Context context,
             @NonNull Supplier<AidlSession> lazyDaemon, int userId, @NonNull String owner,
             int sensorId, @NonNull BiometricLogger logger,
-            @NonNull BiometricContext biometricContext, @NonNull List<Face> enrolledList,
+            @NonNull BiometricContext biometricContext,
             @NonNull BiometricUtils<Face> utils, @NonNull Map<Integer, Long> authenticatorIds) {
         super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
-                enrolledList, utils, authenticatorIds);
+                utils, authenticatorIds);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index cf8ea86..1a53fec 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -597,14 +597,13 @@
     public void scheduleInternalCleanup(int sensorId, int userId,
             @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) {
         mHandler.post(() -> {
-            final List<Face> enrolledList = getEnrolledFaces(sensorId, userId);
             final FaceInternalCleanupClient client =
                     new FaceInternalCleanupClient(mContext,
                             mSensors.get(sensorId).getLazySession(), userId,
                             mContext.getOpPackageName(), sensorId,
                             createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
                                     BiometricsProtoEnums.CLIENT_UNKNOWN),
-                            mBiometricContext, enrolledList,
+                            mBiometricContext,
                             FaceUtils.getInstance(sensorId),
                             mSensors.get(sensorId).getAuthenticatorIds());
             if (favorHalEnrollments) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 0f22296..1e33c96 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -818,12 +818,11 @@
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
 
-            final List<Face> enrolledList = getEnrolledFaces(mSensorId, userId);
             final FaceInternalCleanupClient client = new FaceInternalCleanupClient(mContext,
                     mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId,
                     createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
                             BiometricsProtoEnums.CLIENT_UNKNOWN),
-                    mBiometricContext, enrolledList,
+                    mBiometricContext,
                     FaceUtils.getLegacyInstance(mSensorId), mAuthenticatorIds);
             mScheduler.scheduleClientMonitor(client, new ClientMonitorCompositeCallback(callback,
                     mBiometricStateCallback));
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
index d21a750..89a17c6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
@@ -42,10 +42,10 @@
     FaceInternalCleanupClient(@NonNull Context context,
             @NonNull Supplier<IBiometricsFace> lazyDaemon, int userId, @NonNull String owner,
             int sensorId, @NonNull BiometricLogger logger,
-            @NonNull BiometricContext biometricContext, @NonNull List<Face> enrolledList,
+            @NonNull BiometricContext biometricContext,
             @NonNull BiometricUtils<Face> utils, @NonNull Map<Integer, Long> authenticatorIds) {
         super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
-                enrolledList, utils, authenticatorIds);
+                utils, authenticatorIds);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 8a33f22..f6c1375 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -427,13 +427,6 @@
                 return -1;
             }
 
-            if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, options.getUserId())) {
-                // If this happens, something in KeyguardUpdateMonitor is wrong. This should only
-                // ever be invoked when the user is encrypted or lockdown.
-                Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown");
-                return -1;
-            }
-
             final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
             if (provider == null) {
                 Slog.w(TAG, "Null provider for detectFingerprint");
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
index c315ccf..ff9127f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
@@ -45,10 +45,9 @@
             @NonNull Supplier<AidlSession> lazyDaemon,
             int userId, @NonNull String owner, int sensorId,
             @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            @NonNull List<Fingerprint> enrolledList,
             @NonNull FingerprintUtils utils, @NonNull Map<Integer, Long> authenticatorIds) {
         super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
-                enrolledList, utils, authenticatorIds);
+                utils, authenticatorIds);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index a833278..23b6f84 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -562,7 +562,6 @@
     public void scheduleInternalCleanup(int sensorId, int userId,
             @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments) {
         mHandler.post(() -> {
-            final List<Fingerprint> enrolledList = getEnrolledFingerprints(sensorId, userId);
             final FingerprintInternalCleanupClient client =
                     new FingerprintInternalCleanupClient(mContext,
                             mSensors.get(sensorId).getLazySession(), userId,
@@ -570,7 +569,7 @@
                             createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
                                     BiometricsProtoEnums.CLIENT_UNKNOWN),
                             mBiometricContext,
-                            enrolledList, FingerprintUtils.getInstance(sensorId),
+                            FingerprintUtils.getInstance(sensorId),
                             mSensors.get(sensorId).getAuthenticatorIds());
             if (favorHalEnrollments) {
                 client.setFavorHalEnrollments();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 99c491a..9e6f4e4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -742,14 +742,12 @@
         mHandler.post(() -> {
             scheduleUpdateActiveUserWithoutHandler(userId);
 
-            final List<Fingerprint> enrolledList = getEnrolledFingerprints(
-                    mSensorProperties.sensorId, userId);
             final FingerprintInternalCleanupClient client = new FingerprintInternalCleanupClient(
                     mContext, mLazyDaemon, userId, mContext.getOpPackageName(),
                     mSensorProperties.sensorId,
                     createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
                             BiometricsProtoEnums.CLIENT_UNKNOWN),
-                    mBiometricContext, enrolledList,
+                    mBiometricContext,
                     FingerprintUtils.getLegacyInstance(mSensorId), mAuthenticatorIds);
             mScheduler.scheduleClientMonitor(client, callback);
         });
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
index 5e7cf35..8b61f59 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
@@ -45,11 +45,10 @@
             @NonNull Supplier<IBiometricsFingerprint> lazyDaemon, int userId,
             @NonNull String owner, int sensorId,
             @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
-            @NonNull List<Fingerprint> enrolledList,
             @NonNull BiometricUtils<Fingerprint> utils,
             @NonNull Map<Integer, Long> authenticatorIds) {
         super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
-                enrolledList, utils, authenticatorIds);
+                utils, authenticatorIds);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index dd92ffc..fab138b 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -18,9 +18,9 @@
 
 import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
 import static android.companion.virtual.VirtualDeviceManager.ACTION_VIRTUAL_DEVICE_REMOVED;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_INVALID;
 import static android.companion.virtual.VirtualDeviceManager.EXTRA_VIRTUAL_DEVICE_ID;
+import static android.content.Context.DEVICE_ID_DEFAULT;
+import static android.content.Context.DEVICE_ID_INVALID;
 
 import android.Manifest;
 import android.annotation.NonNull;
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index 3a4aaa7..1f82961 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -31,7 +31,9 @@
 import android.net.metrics.NetworkMetrics;
 import android.net.metrics.WakeupEvent;
 import android.net.metrics.WakeupStats;
+import android.os.BatteryStatsInternal;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -44,6 +46,7 @@
 import com.android.internal.util.RingBuffer;
 import com.android.internal.util.TokenBucket;
 import com.android.net.module.util.BaseNetdEventListener;
+import com.android.server.LocalServices;
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent;
 
 import java.io.PrintWriter;
@@ -74,7 +77,7 @@
     // TODO: dedup this String constant with the one used in
     // ConnectivityService#wakeupModifyInterface().
     @VisibleForTesting
-    static final String WAKEUP_EVENT_IFACE_PREFIX = "iface:";
+    static final String WAKEUP_EVENT_PREFIX_DELIM = ":";
 
     // Array of aggregated DNS and connect events sent by netd, grouped by net id.
     @GuardedBy("this")
@@ -278,17 +281,14 @@
     @Override
     public synchronized void onWakeupEvent(String prefix, int uid, int ethertype, int ipNextHeader,
             byte[] dstHw, String srcIp, String dstIp, int srcPort, int dstPort, long timestampNs) {
-        String iface = prefix.replaceFirst(WAKEUP_EVENT_IFACE_PREFIX, "");
-        final long timestampMs;
-        if (timestampNs > 0) {
-            timestampMs = timestampNs / NANOS_PER_MS;
-        } else {
-            timestampMs = System.currentTimeMillis();
+        final String[] prefixParts = prefix.split(WAKEUP_EVENT_PREFIX_DELIM);
+        if (prefixParts.length != 2) {
+            throw new IllegalArgumentException("Prefix " + prefix
+                    + " required in format <nethandle>:<interface>");
         }
 
-        WakeupEvent event = new WakeupEvent();
-        event.iface = iface;
-        event.timestampMs = timestampMs;
+        final WakeupEvent event = new WakeupEvent();
+        event.iface = prefixParts[1];
         event.uid = uid;
         event.ethertype = ethertype;
         event.dstHwAddr = MacAddress.fromBytes(dstHw);
@@ -297,11 +297,25 @@
         event.ipNextHeader = ipNextHeader;
         event.srcPort = srcPort;
         event.dstPort = dstPort;
+        if (timestampNs > 0) {
+            event.timestampMs = timestampNs / NANOS_PER_MS;
+        } else {
+            event.timestampMs = System.currentTimeMillis();
+        }
         addWakeupEvent(event);
 
-        String dstMac = event.dstHwAddr.toString();
+        final BatteryStatsInternal bsi = LocalServices.getService(BatteryStatsInternal.class);
+        if (bsi != null) {
+            final long netHandle = Long.parseLong(prefixParts[0]);
+            final long elapsedMs = SystemClock.elapsedRealtime() + event.timestampMs
+                    - System.currentTimeMillis();
+            bsi.noteCpuWakingNetworkPacket(Network.fromNetworkHandle(netHandle), elapsedMs,
+                    event.uid);
+        }
+
+        final String dstMac = event.dstHwAddr.toString();
         FrameworkStatsLog.write(FrameworkStatsLog.PACKET_WAKEUP_OCCURRED,
-                uid, iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort);
+                uid, event.iface, ethertype, dstMac, srcIp, dstIp, ipNextHeader, srcPort, dstPort);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 6e1640d..22b6a53 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -35,7 +35,6 @@
 import android.hardware.SensorManager;
 import android.hardware.display.AmbientBrightnessDayStats;
 import android.hardware.display.BrightnessChangeEvent;
-import android.hardware.display.BrightnessConfiguration;
 import android.hardware.display.ColorDisplayManager;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.DisplayManagerInternal;
@@ -126,7 +125,7 @@
     private static final int MSG_BRIGHTNESS_CHANGED = 1;
     private static final int MSG_STOP_SENSOR_LISTENER = 2;
     private static final int MSG_START_SENSOR_LISTENER = 3;
-    private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4;
+    private static final int MSG_SHOULD_COLLECT_COLOR_SAMPLE_CHANGED = 4;
     private static final int MSG_SENSOR_CHANGED = 5;
 
     private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
@@ -162,7 +161,7 @@
     private boolean mColorSamplingEnabled;
     private int mNoFramesToSample;
     private float mFrameRate;
-    private BrightnessConfiguration mBrightnessConfiguration;
+    private boolean mShouldCollectColorSample = false;
     // End of block of members that should only be accessed on the mBgHandler thread.
 
     private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL;
@@ -208,9 +207,9 @@
     /**
      * Update tracker with new brightness configuration.
      */
-    public void setBrightnessConfiguration(BrightnessConfiguration brightnessConfiguration) {
-        mBgHandler.obtainMessage(MSG_BRIGHTNESS_CONFIG_CHANGED,
-                brightnessConfiguration).sendToTarget();
+    public void setShouldCollectColorSample(boolean shouldCollectColorSample) {
+        mBgHandler.obtainMessage(MSG_SHOULD_COLLECT_COLOR_SAMPLE_CHANGED,
+                shouldCollectColorSample).sendToTarget();
     }
 
     private void backgroundStart(float initialBrightness) {
@@ -320,7 +319,7 @@
      * Notify the BrightnessTracker that the user has changed the brightness of the display.
      */
     public void notifyBrightnessChanged(float brightness, boolean userInitiated,
-            float powerBrightnessFactor, boolean isUserSetBrightness,
+            float powerBrightnessFactor, boolean wasShortTermModelActive,
             boolean isDefaultBrightnessConfig, String uniqueDisplayId, float[] luxValues,
             long[] luxTimestamps) {
         if (DEBUG) {
@@ -329,7 +328,7 @@
         }
         Message m = mBgHandler.obtainMessage(MSG_BRIGHTNESS_CHANGED,
                 userInitiated ? 1 : 0, 0 /*unused*/, new BrightnessChangeValues(brightness,
-                        powerBrightnessFactor, isUserSetBrightness, isDefaultBrightnessConfig,
+                        powerBrightnessFactor, wasShortTermModelActive, isDefaultBrightnessConfig,
                         mInjector.currentTimeMillis(), uniqueDisplayId, luxValues, luxTimestamps));
         m.sendToTarget();
     }
@@ -343,7 +342,7 @@
     }
 
     private void handleBrightnessChanged(float brightness, boolean userInitiated,
-            float powerBrightnessFactor, boolean isUserSetBrightness,
+            float powerBrightnessFactor, boolean wasShortTermModelActive,
             boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId,
             float[] luxValues, long[] luxTimestamps) {
         BrightnessChangeEvent.Builder builder;
@@ -368,7 +367,7 @@
             builder.setBrightness(brightness);
             builder.setTimeStamp(timestamp);
             builder.setPowerBrightnessFactor(powerBrightnessFactor);
-            builder.setUserBrightnessPoint(isUserSetBrightness);
+            builder.setUserBrightnessPoint(wasShortTermModelActive);
             builder.setIsDefaultBrightnessConfig(isDefaultBrightnessConfig);
             builder.setUniqueDisplayId(uniqueDisplayId);
 
@@ -827,8 +826,7 @@
         if (!mInjector.isBrightnessModeAutomatic(mContentResolver)
                 || !mInjector.isInteractive(mContext)
                 || mColorSamplingEnabled
-                || mBrightnessConfiguration == null
-                || !mBrightnessConfiguration.shouldCollectColorSamples()) {
+                || !mShouldCollectColorSample) {
             return;
         }
 
@@ -997,7 +995,7 @@
                     BrightnessChangeValues values = (BrightnessChangeValues) msg.obj;
                     boolean userInitiatedChange = (msg.arg1 == 1);
                     handleBrightnessChanged(values.brightness, userInitiatedChange,
-                            values.powerBrightnessFactor, values.isUserSetBrightness,
+                            values.powerBrightnessFactor, values.wasShortTermModelActive,
                             values.isDefaultBrightnessConfig, values.timestamp,
                             values.uniqueDisplayId, values.luxValues, values.luxTimestamps);
                     break;
@@ -1009,14 +1007,11 @@
                     stopSensorListener();
                     disableColorSampling();
                     break;
-                case MSG_BRIGHTNESS_CONFIG_CHANGED:
-                    mBrightnessConfiguration = (BrightnessConfiguration) msg.obj;
-                    boolean shouldCollectColorSamples =
-                            mBrightnessConfiguration != null
-                                    && mBrightnessConfiguration.shouldCollectColorSamples();
-                    if (shouldCollectColorSamples && !mColorSamplingEnabled) {
+                case MSG_SHOULD_COLLECT_COLOR_SAMPLE_CHANGED:
+                    mShouldCollectColorSample = (boolean) msg.obj;
+                    if (mShouldCollectColorSample && !mColorSamplingEnabled) {
                         enableColorSampling();
-                    } else if (!shouldCollectColorSamples && mColorSamplingEnabled) {
+                    } else if (!mShouldCollectColorSample && mColorSamplingEnabled) {
                         disableColorSampling();
                     }
                     break;
@@ -1031,7 +1026,7 @@
     private static class BrightnessChangeValues {
         public final float brightness;
         public final float powerBrightnessFactor;
-        public final boolean isUserSetBrightness;
+        public final boolean wasShortTermModelActive;
         public final boolean isDefaultBrightnessConfig;
         public final long timestamp;
         public final String uniqueDisplayId;
@@ -1039,11 +1034,11 @@
         public final long[] luxTimestamps;
 
         BrightnessChangeValues(float brightness, float powerBrightnessFactor,
-                boolean isUserSetBrightness, boolean isDefaultBrightnessConfig,
+                boolean wasShortTermModelActive, boolean isDefaultBrightnessConfig,
                 long timestamp, String uniqueDisplayId, float[] luxValues, long[] luxTimestamps) {
             this.brightness = brightness;
             this.powerBrightnessFactor = powerBrightnessFactor;
-            this.isUserSetBrightness = isUserSetBrightness;
+            this.wasShortTermModelActive = wasShortTermModelActive;
             this.isDefaultBrightnessConfig = isDefaultBrightnessConfig;
             this.timestamp = timestamp;
             this.uniqueDisplayId = uniqueDisplayId;
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 99e709e..d57dc47 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -22,11 +22,14 @@
 import android.graphics.Rect;
 import android.hardware.display.DisplayViewport;
 import android.os.IBinder;
+import android.util.Slog;
 import android.view.Display;
 import android.view.DisplayAddress;
 import android.view.Surface;
 import android.view.SurfaceControl;
 
+import com.android.server.display.mode.DisplayModeDirector;
+
 import java.io.PrintWriter;
 
 /**
@@ -37,6 +40,7 @@
  * </p>
  */
 abstract class DisplayDevice {
+    private static final String TAG = "DisplayDevice";
     private static final Display.Mode EMPTY_DISPLAY_MODE = new Display.Mode.Builder().build();
 
     private final DisplayAdapter mDisplayAdapter;
@@ -267,10 +271,13 @@
     /**
      * Sets the display layer stack while in a transaction.
      */
-    public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack) {
+    public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack,
+            int layerStackTag) {
         if (mCurrentLayerStack != layerStack) {
             mCurrentLayerStack = layerStack;
             t.setDisplayLayerStack(mDisplayToken, layerStack);
+            Slog.i(TAG, "[" + layerStackTag + "] Layerstack set to " + layerStack + " for "
+                    + mUniqueId);
         }
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index d9b3501..75f8acc 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -1260,7 +1260,7 @@
         return mAmbientDarkeningPercentagesIdle;
     }
 
-    SensorData getAmbientLightSensor() {
+    public SensorData getAmbientLightSensor() {
         return mAmbientLightSensor;
     }
 
@@ -2821,7 +2821,7 @@
     /**
      * Uniquely identifies a Sensor, with the combination of Type and Name.
      */
-    static class SensorData {
+    public static class SensorData {
         public String type;
         public String name;
         public float minRefreshRate = 0.0f;
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6eb465e..21cc172 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -152,6 +152,7 @@
 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.mode.DisplayModeDirector;
 import com.android.server.display.utils.SensorUtils;
 import com.android.server.input.InputManagerInternal;
 import com.android.server.wm.SurfaceAnimationThread;
@@ -2104,8 +2105,7 @@
         }
     }
 
-    // TODO (b/264979880) - Add unit test for HDR output control methods.
-    private void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) {
+    void setHdrConversionModeInternal(HdrConversionMode hdrConversionMode) {
         if (!mInjector.getHdrOutputConversionSupport()) {
             return;
         }
@@ -2139,7 +2139,7 @@
         }
     }
 
-    private HdrConversionMode getHdrConversionModeSettingInternal() {
+    HdrConversionMode getHdrConversionModeSettingInternal() {
         if (!mInjector.getHdrOutputConversionSupport()) {
             return HDR_CONVERSION_MODE_UNSUPPORTED;
         }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 9917bfc..84fe8f2 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -885,7 +885,7 @@
         final boolean isInTransition = mLogicalDisplay.isInTransitionLocked();
         final String brightnessThrottlingDataId =
                 mLogicalDisplay.getBrightnessThrottlingDataIdLocked();
-        mHandler.post(() -> {
+        mHandler.postAtTime(() -> {
             boolean changed = false;
             if (mDisplayDevice != device) {
                 changed = true;
@@ -916,7 +916,7 @@
             if (changed) {
                 updatePowerState();
             }
-        });
+        }, mClock.uptimeMillis());
     }
 
     /**
@@ -940,10 +940,6 @@
                 mAutomaticBrightnessController.stop();
             }
 
-            if (mScreenOffBrightnessSensorController != null) {
-                mScreenOffBrightnessSensorController.stop();
-            }
-
             if (mBrightnessSetting != null) {
                 mBrightnessSetting.unregisterListener(mBrightnessSettingListener);
             }
@@ -1190,6 +1186,7 @@
 
             if (mScreenOffBrightnessSensorController != null) {
                 mScreenOffBrightnessSensorController.stop();
+                mScreenOffBrightnessSensorController = null;
             }
             loadScreenOffBrightnessSensor();
             int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
@@ -1311,6 +1308,10 @@
             mPowerState.stop();
             mPowerState = null;
         }
+
+        if (mScreenOffBrightnessSensorController != null) {
+            mScreenOffBrightnessSensorController.stop();
+        }
     }
 
     private void updatePowerState() {
@@ -1538,10 +1539,10 @@
         // user, or is a temporary adjustment.
         boolean userInitiatedChange = (Float.isNaN(brightnessState))
                 && (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
-        boolean hadUserBrightnessPoint = false;
+        boolean wasShortTermModelActive = false;
         // Configure auto-brightness.
         if (mAutomaticBrightnessController != null) {
-            hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
+            wasShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints();
             mAutomaticBrightnessController.configure(autoBrightnessState,
                     mBrightnessConfiguration,
                     mLastUserSetScreenBrightness,
@@ -1555,7 +1556,8 @@
                 : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED);
 
         if (mBrightnessTracker != null) {
-            mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
+            mBrightnessTracker.setShouldCollectColorSample(mBrightnessConfiguration != null
+                    && mBrightnessConfiguration.shouldCollectColorSamples());
         }
 
         boolean updateScreenBrightnessSetting = false;
@@ -1823,7 +1825,7 @@
                     userInitiatedChange = false;
                 }
                 notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
-                        hadUserBrightnessPoint);
+                        wasShortTermModelActive);
             }
 
             // We save the brightness info *after* the brightness setting has been changed and
@@ -1865,7 +1867,7 @@
         mTempBrightnessEvent.setRbcStrength(mCdsi != null
                 ? mCdsi.getReduceBrightColorsStrength() : -1);
         mTempBrightnessEvent.setPowerFactor(mPowerRequest.screenLowPowerBrightnessFactor);
-        mTempBrightnessEvent.setWasShortTermModelActive(hadUserBrightnessPoint);
+        mTempBrightnessEvent.setWasShortTermModelActive(wasShortTermModelActive);
         // Temporary is what we use during slider interactions. We avoid logging those so that
         // we don't spam logcat when the slider is being used.
         boolean tempToTempTransition =
@@ -2634,7 +2636,7 @@
     }
 
     private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated,
-            boolean hadUserDataPoint) {
+            boolean wasShortTermModelActive) {
         final float brightnessInNits = convertToNits(brightness);
         if (mUseAutoBrightness && brightnessInNits >= 0.0f
                 && mAutomaticBrightnessController != null && mBrightnessTracker != null) {
@@ -2645,7 +2647,7 @@
                     ? mPowerRequest.screenLowPowerBrightnessFactor
                     : 1.0f;
             mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
-                    powerFactor, hadUserDataPoint,
+                    powerFactor, wasShortTermModelActive,
                     mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
                     mAutomaticBrightnessController.getLastSensorValues(),
                     mAutomaticBrightnessController.getLastSensorTimestamps());
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index f49419cf..297a6f8 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -729,7 +729,7 @@
         final String brightnessThrottlingDataId =
                 mLogicalDisplay.getBrightnessThrottlingDataIdLocked();
 
-        mHandler.post(() -> {
+        mHandler.postAtTime(() -> {
             boolean changed = false;
             if (mDisplayDevice != device) {
                 changed = true;
@@ -761,7 +761,7 @@
             if (changed) {
                 updatePowerState();
             }
-        });
+        }, mClock.uptimeMillis());
     }
 
     /**
@@ -1028,6 +1028,10 @@
             mBrightnessEventRingBuffer =
                     new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX);
 
+            if (mScreenOffBrightnessSensorController != null) {
+                mScreenOffBrightnessSensorController.stop();
+                mScreenOffBrightnessSensorController = null;
+            }
             loadScreenOffBrightnessSensor();
             int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
             if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
@@ -1133,6 +1137,10 @@
             mPowerState.stop();
             mPowerState = null;
         }
+
+        if (mScreenOffBrightnessSensorController != null) {
+            mScreenOffBrightnessSensorController.stop();
+        }
     }
 
     private void updatePowerState() {
@@ -1250,10 +1258,10 @@
         // user, or is a temporary adjustment.
         boolean userInitiatedChange = (Float.isNaN(brightnessState))
                 && (autoBrightnessAdjustmentChanged || userSetBrightnessChanged);
-        boolean hadUserBrightnessPoint = false;
+        boolean wasShortTermModelActive = false;
         // Configure auto-brightness.
         if (mAutomaticBrightnessController != null) {
-            hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
+            wasShortTermModelActive = mAutomaticBrightnessController.hasUserDataPoints();
             mAutomaticBrightnessController.configure(autoBrightnessState,
                     mBrightnessConfiguration,
                     mDisplayBrightnessController.getLastUserSetScreenBrightness(),
@@ -1267,7 +1275,8 @@
                 : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED);
 
         if (mBrightnessTracker != null) {
-            mBrightnessTracker.setBrightnessConfiguration(mBrightnessConfiguration);
+            mBrightnessTracker.setShouldCollectColorSample(mBrightnessConfiguration != null
+                    && mBrightnessConfiguration.shouldCollectColorSamples());
         }
 
         boolean updateScreenBrightnessSetting = false;
@@ -1537,7 +1546,7 @@
                     userInitiatedChange = false;
                 }
                 notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
-                        hadUserBrightnessPoint);
+                        wasShortTermModelActive);
             }
 
             // We save the brightness info *after* the brightness setting has been changed and
@@ -1579,7 +1588,7 @@
         mTempBrightnessEvent.setRbcStrength(mCdsi != null
                 ? mCdsi.getReduceBrightColorsStrength() : -1);
         mTempBrightnessEvent.setPowerFactor(mPowerRequest.screenLowPowerBrightnessFactor);
-        mTempBrightnessEvent.setWasShortTermModelActive(hadUserBrightnessPoint);
+        mTempBrightnessEvent.setWasShortTermModelActive(wasShortTermModelActive);
         mTempBrightnessEvent.setDisplayBrightnessStrategyName(displayBrightnessState
                 .getDisplayBrightnessStrategyName());
         // Temporary is what we use during slider interactions. We avoid logging those so that
@@ -2220,7 +2229,7 @@
     }
 
     private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated,
-            boolean hadUserDataPoint) {
+            boolean wasShortTermModelActive) {
         final float brightnessInNits = convertToNits(brightness);
         if (mUseAutoBrightness && brightnessInNits >= 0.0f
                 && mAutomaticBrightnessController != null && mBrightnessTracker != null) {
@@ -2231,7 +2240,7 @@
                     ? mPowerRequest.screenLowPowerBrightnessFactor
                     : 1.0f;
             mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
-                    powerFactor, hadUserDataPoint,
+                    powerFactor, wasShortTermModelActive,
                     mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
                     mAutomaticBrightnessController.getLastSensorValues(),
                     mAutomaticBrightnessController.getLastSensorTimestamps());
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 8f52c97..58c5034 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -46,6 +46,7 @@
 import com.android.internal.display.BrightnessSynchronizer;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.LocalServices;
+import com.android.server.display.mode.DisplayModeDirector;
 import com.android.server.lights.LightsManager;
 import com.android.server.lights.LogicalLight;
 
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index fc90db6..04532f9 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -33,6 +33,7 @@
 import android.view.SurfaceControl;
 
 import com.android.server.display.layout.Layout;
+import com.android.server.display.mode.DisplayModeDirector;
 import com.android.server.wm.utils.InsetUtils;
 
 import java.io.PrintWriter;
@@ -571,7 +572,7 @@
             DisplayDevice device,
             boolean isBlanked) {
         // Set the layer stack.
-        device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
+        device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack, mDisplayId);
         // Also inform whether the device is the same one sent to inputflinger for its layerstack.
         // Prevent displays that are disabled from receiving input.
         // TODO(b/188914255): Remove once input can dispatch against device vs layerstack.
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 3e67f0a..2ce7690 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -36,6 +36,7 @@
 
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.display.mode.DisplayModeDirector;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
similarity index 98%
rename from services/core/java/com/android/server/display/DisplayModeDirector.java
rename to services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 31f5ab7..24d5ca4 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.display;
+package com.android.server.display.mode;
 
 import static android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED;
 import static android.hardware.display.DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE;
@@ -67,6 +67,7 @@
 import com.android.internal.display.BrightnessSynchronizer;
 import com.android.internal.os.BackgroundThread;
 import com.android.server.LocalServices;
+import com.android.server.display.DisplayDeviceConfig;
 import com.android.server.display.utils.AmbientFilter;
 import com.android.server.display.utils.AmbientFilterFactory;
 import com.android.server.display.utils.SensorUtils;
@@ -214,6 +215,9 @@
         mUdfpsObserver.observe();
     }
 
+    /**
+    * Enables or disables component logging
+    */
     public void setLoggingEnabled(boolean loggingEnabled) {
         if (mLoggingEnabled == loggingEnabled) {
             return;
@@ -1574,7 +1578,10 @@
         }
     }
 
-    final class AppRequestObserver {
+    /**
+     *  Responsible for keeping track of app requested refresh rates per display
+     */
+    public final class AppRequestObserver {
         private final SparseArray<Display.Mode> mAppRequestedModeByDisplay;
         private final SparseArray<RefreshRateRange> mAppPreferredRefreshRateRangeByDisplay;
 
@@ -1583,6 +1590,9 @@
             mAppPreferredRefreshRateRangeByDisplay = new SparseArray<>();
         }
 
+        /**
+         * Sets refresh rates from app request
+         */
         public void setAppRequest(int displayId, int modeId, float requestedMinRefreshRateRange,
                 float requestedMaxRefreshRateRange) {
             synchronized (mLock) {
@@ -1665,7 +1675,7 @@
             return null;
         }
 
-        public void dumpLocked(PrintWriter pw) {
+        private void dumpLocked(PrintWriter pw) {
             pw.println("  AppRequestObserver");
             pw.println("    mAppRequestedModeByDisplay:");
             for (int i = 0; i < mAppRequestedModeByDisplay.size(); i++) {
@@ -1794,7 +1804,7 @@
      */
     @VisibleForTesting
     public class BrightnessObserver implements DisplayManager.DisplayListener {
-        private final static int LIGHT_SENSOR_RATE_MS = 250;
+        private static final int LIGHT_SENSOR_RATE_MS = 250;
         private int[] mLowDisplayBrightnessThresholds;
         private int[] mLowAmbientBrightnessThresholds;
         private int[] mHighDisplayBrightnessThresholds;
@@ -2019,7 +2029,7 @@
             return mLowAmbientBrightnessThresholds;
         }
 
-        public void observe(SensorManager sensorManager) {
+        private void observe(SensorManager sensorManager) {
             mSensorManager = sensorManager;
             mBrightness = getBrightness(Display.DEFAULT_DISPLAY);
 
@@ -2064,11 +2074,11 @@
             mDeviceConfigDisplaySettings.startListening();
 
             mInjector.registerDisplayListener(this, mHandler,
-                    DisplayManager.EVENT_FLAG_DISPLAY_CHANGED |
-                    DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
+                    DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
+                            | DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
         }
 
-        public void setLoggingEnabled(boolean loggingEnabled) {
+        private void setLoggingEnabled(boolean loggingEnabled) {
             if (mLoggingEnabled == loggingEnabled) {
                 return;
             }
@@ -2076,7 +2086,8 @@
             mLightSensorListener.setLoggingEnabled(loggingEnabled);
         }
 
-        public void onRefreshRateSettingChangedLocked(float min, float max) {
+        @VisibleForTesting
+        void onRefreshRateSettingChangedLocked(float min, float max) {
             boolean changeable = (max - min > 1f && max > 60f);
             if (mRefreshRateChangeable != changeable) {
                 mRefreshRateChangeable = changeable;
@@ -2089,14 +2100,14 @@
             }
         }
 
-        public void onLowPowerModeEnabledLocked(boolean b) {
+        private void onLowPowerModeEnabledLocked(boolean b) {
             if (mLowPowerModeEnabled != b) {
                 mLowPowerModeEnabled = b;
                 updateSensorStatus();
             }
         }
 
-        public void onDeviceConfigLowBrightnessThresholdsChanged(int[] displayThresholds,
+        private void onDeviceConfigLowBrightnessThresholdsChanged(int[] displayThresholds,
                 int[] ambientThresholds) {
             if (displayThresholds != null && ambientThresholds != null
                     && displayThresholds.length == ambientThresholds.length) {
@@ -2123,7 +2134,7 @@
             }
         }
 
-        public void onDeviceConfigHighBrightnessThresholdsChanged(int[] displayThresholds,
+        private void onDeviceConfigHighBrightnessThresholdsChanged(int[] displayThresholds,
                 int[] ambientThresholds) {
             if (displayThresholds != null && ambientThresholds != null
                     && displayThresholds.length == ambientThresholds.length) {
@@ -2150,7 +2161,7 @@
             }
         }
 
-        public void dumpLocked(PrintWriter pw) {
+        void dumpLocked(PrintWriter pw) {
             pw.println("  BrightnessObserver");
             pw.println("    mAmbientLux: " + mAmbientLux);
             pw.println("    mBrightness: " + mBrightness);
@@ -2400,7 +2411,7 @@
         }
 
         @VisibleForTesting
-        public void setDefaultDisplayState(int state) {
+        void setDefaultDisplayState(int state) {
             if (mLoggingEnabled) {
                 Slog.d(TAG, "setDefaultDisplayState: mDefaultDisplayState = "
                         + mDefaultDisplayState + ", state = " + state);
@@ -2475,7 +2486,7 @@
         }
 
         private final class LightSensorEventListener implements SensorEventListener {
-            final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
+            private static final int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
             private float mLastSensorData;
             private long mTimestamp;
             private boolean mLoggingEnabled;
@@ -2876,10 +2887,10 @@
             }
 
             final int hbmMode = info.highBrightnessMode;
-            final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF &&
-                info.adjustedBrightness > info.highBrightnessTransitionPoint;
-            if (hbmMode == mHbmMode.get(displayId) &&
-                isHbmActive == mHbmActive.get(displayId)) {
+            final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF
+                    && info.adjustedBrightness > info.highBrightnessTransitionPoint;
+            if (hbmMode == mHbmMode.get(displayId)
+                    && isHbmActive == mHbmActive.get(displayId)) {
                 // no change, ignore.
                 return;
             }
@@ -2901,7 +2912,7 @@
             Vote vote = null;
             if (mHbmActive.get(displayId, false)) {
                 final int hbmMode =
-                    mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
+                        mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
                 if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
                     // Device resource properties take priority over DisplayDeviceConfig
                     if (mRefreshRateInHbmSunlight > 0) {
@@ -2909,7 +2920,7 @@
                                 mRefreshRateInHbmSunlight);
                     } else {
                         final List<RefreshRateLimitation> limits =
-                            mDisplayManagerInternal.getRefreshRateLimitations(displayId);
+                                mDisplayManagerInternal.getRefreshRateLimitations(displayId);
                         for (int i = 0; limits != null && i < limits.size(); i++) {
                             final RefreshRateLimitation limitation = limits.get(i);
                             if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
@@ -2919,8 +2930,8 @@
                             }
                         }
                     }
-                } else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR &&
-                        mRefreshRateInHbmHdr > 0) {
+                } else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
+                        && mRefreshRateInHbmHdr > 0) {
                     // HBM for HDR vote isn't supported through DisplayDeviceConfig yet, so look for
                     // a vote from Device properties
                     vote = Vote.forPhysicalRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
@@ -2988,9 +2999,6 @@
     }
 
     private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
-        public DeviceConfigDisplaySettings() {
-        }
-
         public void startListening() {
             mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                     BackgroundThread.getExecutor(), this);
@@ -3001,8 +3009,8 @@
          */
         public int[] getLowDisplayBrightnessThresholds() {
             return getIntArrayProperty(
-                    DisplayManager.DeviceConfig.
-                            KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS);
+                    DisplayManager.DeviceConfig
+                            .KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS);
         }
 
         /*
@@ -3010,8 +3018,8 @@
          */
         public int[] getLowAmbientBrightnessThresholds() {
             return getIntArrayProperty(
-                    DisplayManager.DeviceConfig.
-                            KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS);
+                    DisplayManager.DeviceConfig
+                            .KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS);
         }
 
         public int getRefreshRateInLowZone() {
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 3bc4b54..3e2efdd 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -158,15 +158,14 @@
             final DreamRecord oldDream = mCurrentDream;
             mCurrentDream = new DreamRecord(token, name, isPreviewMode, canDoze, userId, wakeLock);
             if (oldDream != null) {
-                if (!oldDream.mWakingGently) {
-                    // We will stop these previous dreams once the new dream is started.
-                    mPreviousDreams.add(oldDream);
-                } else if (Objects.equals(oldDream.mName, mCurrentDream.mName)) {
+                if (Objects.equals(oldDream.mName, mCurrentDream.mName)) {
                     // We are attempting to start a dream that is currently waking up gently.
                     // Let's silently stop the old instance here to clear the dream state.
                     // This should happen after the new mCurrentDream is set to avoid announcing
                     // a "dream stopped" state.
                     stopDreamInstance(/* immediately */ true, "restarting same dream", oldDream);
+                } else {
+                    mPreviousDreams.add(oldDream);
                 }
             }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 3563938..c0deb3f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -700,6 +700,7 @@
         }
         if (mCecController == null) {
             Slog.i(TAG, "Device does not support HDMI-CEC.");
+            return;
         }
         if (mMhlController == null) {
             mMhlController = HdmiMhlControllerStub.create(this);
@@ -713,9 +714,6 @@
         if (mEarcController == null) {
             Slog.i(TAG, "Device does not support eARC.");
         }
-        if (mCecController == null && mEarcController == null) {
-            return;
-        }
         mHdmiCecNetwork = new HdmiCecNetwork(this, mCecController, mMhlController);
         if (isCecControlEnabled()) {
             initializeCec(INITIATED_BY_BOOT_UP);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
index 0ea64ab..8c7658e 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
@@ -178,6 +178,14 @@
     public abstract void unbindAccessibilityFromCurrentClient(int accessibilityConnectionId);
 
     /**
+     * Switch the keyboard layout in response to a keyboard shortcut.
+     *
+     * @param direction {@code 1} to switch to the next subtype, {@code -1} to switch to the
+     *                           previous subtype.
+     */
+    public abstract void switchKeyboardLayout(int direction);
+
+    /**
      * Fake implementation of {@link InputMethodManagerInternal}.  All the methods do nothing.
      */
     private static final InputMethodManagerInternal NOP =
@@ -256,6 +264,10 @@
                 @Override
                 public void maybeFinishStylusHandwriting() {
                 }
+
+                @Override
+                public void switchKeyboardLayout(int direction) {
+                }
             };
 
     /**
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index f142293..d397a0c 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1410,6 +1410,22 @@
         }
 
         @Override
+        public void onPackageDataCleared(String packageName, int uid) {
+            boolean changed = false;
+            for (InputMethodInfo imi : mMethodList) {
+                if (imi.getPackageName().equals(packageName)) {
+                    mAdditionalSubtypeMap.remove(imi.getId());
+                    changed = true;
+                }
+            }
+            if (changed) {
+                AdditionalSubtypeUtils.save(
+                        mAdditionalSubtypeMap, mMethodMap, mSettings.getCurrentUserId());
+                mChangedPackages.add(packageName);
+            }
+        }
+
+        @Override
         public void onFinishPackageChanges() {
             onFinishPackageChangesInternal();
             clearPackageChangeState();
@@ -2079,7 +2095,7 @@
                     new ArrayMap<>();
             AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
             queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap,
-                    methodList, directBootAwareness);
+                    methodList, directBootAwareness, mSettings.getEnabledInputMethodNames());
             settings = new InputMethodSettings(mContext, methodMap, userId, true /* copyOnWrite */);
         }
         // filter caller's access to input methods
@@ -3263,7 +3279,7 @@
                 notifyInputMethodSubtypeChangedLocked(userId, info, null);
                 return;
             }
-            if (newSubtype != oldSubtype) {
+            if (!newSubtype.equals(oldSubtype)) {
                 setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
                 IInputMethodInvoker curMethod = getCurMethodLocked();
                 if (curMethod != null) {
@@ -4050,17 +4066,22 @@
             if (!calledWithValidTokenLocked(token)) {
                 return false;
             }
-            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
-                    onlyCurrentIme, mMethodMap.get(getSelectedMethodIdLocked()), mCurrentSubtype);
-            if (nextSubtype == null) {
-                return false;
-            }
-            setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(),
-                    nextSubtype.mSubtypeId);
-            return true;
+            return switchToNextInputMethodLocked(token, onlyCurrentIme);
         }
     }
 
+    @GuardedBy("ImfLock.class")
+    private boolean switchToNextInputMethodLocked(@Nullable IBinder token, boolean onlyCurrentIme) {
+        final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
+                onlyCurrentIme, mMethodMap.get(getSelectedMethodIdLocked()), mCurrentSubtype);
+        if (nextSubtype == null) {
+            return false;
+        }
+        setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(),
+                nextSubtype.mSubtypeId);
+        return true;
+    }
+
     @BinderThread
     private boolean shouldOfferSwitchingToNextInputMethod(@NonNull IBinder token) {
         synchronized (ImfLock.class) {
@@ -4136,7 +4157,7 @@
                     new ArrayMap<>();
             AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
             queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap, methodMap,
-                    methodList, DirectBootAwareness.AUTO);
+                    methodList, DirectBootAwareness.AUTO, mSettings.getEnabledInputMethodNames());
             final InputMethodSettings settings = new InputMethodSettings(mContext, methodMap,
                     userId, false);
             settings.setAdditionalInputMethodSubtypes(imiId, toBeAdded, additionalSubtypeMap,
@@ -5033,7 +5054,7 @@
     static void queryInputMethodServicesInternal(Context context,
             @UserIdInt int userId, ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap,
             ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
-            @DirectBootAwareness int directBootAwareness) {
+            @DirectBootAwareness int directBootAwareness, List<String> enabledInputMethodList) {
         final Context userAwareContext = context.getUserId() == userId
                 ? context
                 : context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
@@ -5066,6 +5087,17 @@
         methodList.ensureCapacity(services.size());
         methodMap.ensureCapacity(services.size());
 
+        filterInputMethodServices(additionalSubtypeMap, methodMap, methodList,
+                enabledInputMethodList, userAwareContext, services);
+    }
+
+    static void filterInputMethodServices(
+            ArrayMap<String, List<InputMethodSubtype>> additionalSubtypeMap,
+            ArrayMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList,
+            List<String> enabledInputMethodList, Context userAwareContext,
+            List<ResolveInfo> services) {
+        final ArrayMap<String, Integer> imiPackageCount = new ArrayMap<>();
+
         for (int i = 0; i < services.size(); ++i) {
             ResolveInfo ri = services.get(i);
             ServiceInfo si = ri.serviceInfo;
@@ -5085,10 +5117,21 @@
                 if (imi.isVrOnly()) {
                     continue;  // Skip VR-only IME, which isn't supported for now.
                 }
-                methodList.add(imi);
-                methodMap.put(imi.getId(), imi);
-                if (DEBUG) {
-                    Slog.d(TAG, "Found an input method " + imi);
+                final String packageName = si.packageName;
+                // only include IMEs which are from the system, enabled, or below the threshold
+                if (si.applicationInfo.isSystemApp() || enabledInputMethodList.contains(imi.getId())
+                        || imiPackageCount.getOrDefault(packageName, 0)
+                        < InputMethodInfo.MAX_IMES_PER_PACKAGE) {
+                    imiPackageCount.put(packageName,
+                            1 + imiPackageCount.getOrDefault(packageName, 0));
+
+                    methodList.add(imi);
+                    methodMap.put(imi.getId(), imi);
+                    if (DEBUG) {
+                        Slog.d(TAG, "Found an input method " + imi);
+                    }
+                } else if (DEBUG) {
+                    Slog.d(TAG, "Found an input method, but ignored due threshold: " + imi);
                 }
             } catch (Exception e) {
                 Slog.wtf(TAG, "Unable to load input method " + imeId, e);
@@ -5110,7 +5153,8 @@
         mMyPackageMonitor.clearKnownImePackageNamesLocked();
 
         queryInputMethodServicesInternal(mContext, mSettings.getCurrentUserId(),
-                mAdditionalSubtypeMap, mMethodMap, mMethodList, DirectBootAwareness.AUTO);
+                mAdditionalSubtypeMap, mMethodMap, mMethodList, DirectBootAwareness.AUTO,
+                mSettings.getEnabledInputMethodNames());
 
         // Construct the set of possible IME packages for onPackageChanged() to avoid false
         // negatives when the package state remains to be the same but only the component state is
@@ -5169,7 +5213,7 @@
                             reenableMinimumNonAuxSystemImes);
             final int numImes = defaultEnabledIme.size();
             for (int i = 0; i < numImes; ++i) {
-                final InputMethodInfo imi =  defaultEnabledIme.get(i);
+                final InputMethodInfo imi = defaultEnabledIme.get(i);
                 if (DEBUG) {
                     Slog.d(TAG, "--- enable ime = " + imi);
                 }
@@ -5469,7 +5513,8 @@
                 new ArrayMap<>();
         AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
         queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
-                methodMap, methodList, DirectBootAwareness.AUTO);
+                methodMap, methodList, DirectBootAwareness.AUTO,
+                mSettings.getEnabledInputMethodNames());
         return methodMap;
     }
 
@@ -5725,6 +5770,17 @@
             mHandler.removeMessages(MSG_FINISH_HANDWRITING);
             mHandler.obtainMessage(MSG_FINISH_HANDWRITING).sendToTarget();
         }
+
+        @Override
+        public void switchKeyboardLayout(int direction) {
+            synchronized (ImfLock.class) {
+                if (direction > 0) {
+                    switchToNextInputMethodLocked(null /* token */, true /* onlyCurrentIme */);
+                } else {
+                    // TODO(b/258853866): Support backwards switching.
+                }
+            }
+        }
     }
 
     @BinderThread
@@ -6429,7 +6485,8 @@
                                 new ArrayMap<>();
                         AdditionalSubtypeUtils.load(additionalSubtypeMap, userId);
                         queryInputMethodServicesInternal(mContext, userId, additionalSubtypeMap,
-                                methodMap, methodList, DirectBootAwareness.AUTO);
+                                methodMap, methodList, DirectBootAwareness.AUTO,
+                                mSettings.getEnabledInputMethodNames());
                         final InputMethodSettings settings = new InputMethodSettings(mContext,
                                 methodMap, userId, false);
 
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index 559eb53..17536fc 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -438,6 +438,15 @@
                     mSubtypeSplitter);
         }
 
+        List<String> getEnabledInputMethodNames() {
+            List<String> result = new ArrayList<>();
+            for (Pair<String, ArrayList<String>> pair :
+                    getEnabledInputMethodsAndSubtypeListLocked()) {
+                result.add(pair.first);
+            }
+            return result;
+        }
+
         void appendAndPutEnabledInputMethodLocked(String id, boolean reloadInputMethodStr) {
             if (reloadInputMethodStr) {
                 getEnabledInputMethodsStr();
diff --git a/services/core/java/com/android/server/locales/AppSupportedLocalesChangedAtomRecord.java b/services/core/java/com/android/server/locales/AppSupportedLocalesChangedAtomRecord.java
new file mode 100644
index 0000000..de429f0
--- /dev/null
+++ b/services/core/java/com/android/server/locales/AppSupportedLocalesChangedAtomRecord.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.server.locales;
+
+import static android.os.Process.INVALID_UID;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+/**
+ * Holds data used to report the AppSupportedLocalesChanged atom.
+ */
+public final class AppSupportedLocalesChangedAtomRecord {
+    // The uid which invoked this update.
+    final int mCallingUid;
+    // The uid for which the override of app’s supported locales change is being done.
+    int mTargetUid = INVALID_UID;
+    // The total number of locales in the override LocaleConfig.
+    int mNumLocales = -1;
+    // Whether the override is removed LocaleConfig from the storage.
+    boolean mOverrideRemoved = false;
+    // Whether the new override LocaleConfig is the same as the app’s LocaleConfig.
+    boolean mSameAsResConfig = false;
+    // Whether the new override LocaleConfig is the same as the previously effective one. This means
+    // a comparison with the previous override LocaleConfig if there was one, and a comparison with
+    // the resource LocaleConfig if no override was present.
+    boolean mSameAsPrevConfig = false;
+    // Application supported locales changed status.
+    int mStatus = FrameworkStatsLog
+            .APP_SUPPORTED_LOCALES_CHANGED__STATUS__STATUS_UNSPECIFIED;
+
+    AppSupportedLocalesChangedAtomRecord(int callingUid) {
+        this.mCallingUid = callingUid;
+    }
+
+    void setTargetUid(int targetUid) {
+        this.mTargetUid = targetUid;
+    }
+
+    void setNumLocales(int numLocales) {
+        this.mNumLocales = numLocales;
+    }
+
+    void setOverrideRemoved(boolean overrideRemoved) {
+        this.mOverrideRemoved = overrideRemoved;
+    }
+
+    void setSameAsResConfig(boolean sameAsResConfig) {
+        this.mSameAsResConfig = sameAsResConfig;
+    }
+
+    void setSameAsPrevConfig(boolean sameAsPrevConfig) {
+        this.mSameAsPrevConfig = sameAsPrevConfig;
+    }
+
+    void setStatus(int status) {
+        this.mStatus = status;
+    }
+}
diff --git a/services/core/java/com/android/server/locales/LocaleManagerService.java b/services/core/java/com/android/server/locales/LocaleManagerService.java
index 99d30f5..e5f5897 100644
--- a/services/core/java/com/android/server/locales/LocaleManagerService.java
+++ b/services/core/java/com/android/server/locales/LocaleManagerService.java
@@ -250,7 +250,7 @@
             // set locales if the package name is owned by the app. Next, check if the caller has
             // the necessary permission and set locales.
             boolean isCallerOwner = isPackageOwnedByCaller(appPackageName, userId,
-                    atomRecordForMetrics);
+                    atomRecordForMetrics, null);
             if (!isCallerOwner) {
                 enforceChangeConfigurationPermission(atomRecordForMetrics);
             }
@@ -264,7 +264,7 @@
                 Binder.restoreCallingIdentity(token);
             }
         } finally {
-            logMetric(atomRecordForMetrics);
+            logAppLocalesMetric(atomRecordForMetrics);
         }
     }
 
@@ -355,32 +355,30 @@
     }
 
     /**
-     * Same as {@link LocaleManagerService#isPackageOwnedByCaller(String, int,
-     * AppLocaleChangedAtomRecord)}, but for methods that do not log locale atom.
-     */
-    private boolean isPackageOwnedByCaller(String appPackageName, int userId) {
-        return isPackageOwnedByCaller(appPackageName, userId, /* atomRecordForMetrics= */null);
-    }
-
-    /**
      * Checks if the package is owned by the calling app or not for the given user id.
      *
      * @throws IllegalArgumentException if package not found for given userid
      */
     private boolean isPackageOwnedByCaller(String appPackageName, int userId,
-            @Nullable AppLocaleChangedAtomRecord atomRecordForMetrics) {
+            @Nullable AppLocaleChangedAtomRecord atomRecordForMetrics,
+            @Nullable AppSupportedLocalesChangedAtomRecord appSupportedLocalesChangedAtomRecord) {
         final int uid = getPackageUid(appPackageName, userId);
         if (uid < 0) {
             Slog.w(TAG, "Unknown package " + appPackageName + " for user " + userId);
             if (atomRecordForMetrics != null) {
                 atomRecordForMetrics.setStatus(FrameworkStatsLog
                         .APPLICATION_LOCALES_CHANGED__STATUS__FAILURE_INVALID_TARGET_PACKAGE);
+            } else if (appSupportedLocalesChangedAtomRecord != null) {
+                appSupportedLocalesChangedAtomRecord.setStatus(FrameworkStatsLog
+                        .APP_SUPPORTED_LOCALES_CHANGED__STATUS__FAILURE_INVALID_TARGET_PACKAGE);
             }
             throw new IllegalArgumentException("Unknown package: " + appPackageName
                     + " for user " + userId);
         }
         if (atomRecordForMetrics != null) {
             atomRecordForMetrics.setTargetUid(uid);
+        } else if (appSupportedLocalesChangedAtomRecord != null) {
+            appSupportedLocalesChangedAtomRecord.setTargetUid(uid);
         }
         //Once valid package found, ignore the userId part for validating package ownership
         //as apps with INTERACT_ACROSS_USERS permission could be changing locale for different user.
@@ -425,7 +423,7 @@
         // current input method, and that app is querying locales of the current foreground app. If
         // neither conditions matched, check if the caller has the necessary permission and fetch
         // locales.
-        if (!isPackageOwnedByCaller(appPackageName, userId)
+        if (!isPackageOwnedByCaller(appPackageName, userId, null, null)
                 && !isCallerInstaller(appPackageName, userId)
                 && !(isCallerFromCurrentInputMethod(userId)
                     && mActivityManagerInternal.isAppForeground(
@@ -550,7 +548,7 @@
         return systemLocales;
     }
 
-    private void logMetric(@NonNull AppLocaleChangedAtomRecord atomRecordForMetrics) {
+    private void logAppLocalesMetric(@NonNull AppLocaleChangedAtomRecord atomRecordForMetrics) {
         FrameworkStatsLog.write(FrameworkStatsLog.APPLICATION_LOCALES_CHANGED,
                 atomRecordForMetrics.mCallingUid,
                 atomRecordForMetrics.mTargetUid,
@@ -569,33 +567,39 @@
             return;
         }
 
-        requireNonNull(appPackageName);
-
-        //Allow apps with INTERACT_ACROSS_USERS permission to set locales for different user.
-        userId = mActivityManagerInternal.handleIncomingUser(
-                Binder.getCallingPid(), Binder.getCallingUid(), userId,
-                false /* allowAll */, ActivityManagerInternal.ALLOW_NON_FULL,
-                "setOverrideLocaleConfig", /* callerPackage= */ null);
-
-        // This function handles two types of set operations:
-        // 1.) A normal, an app overrides its own LocaleConfig.
-        // 2.) A privileged system application or service is granted the necessary permission to
-        // override a LocaleConfig of another package.
-        if (!isPackageOwnedByCaller(appPackageName, userId)) {
-            enforceSetAppSpecificLocaleConfigPermission();
-        }
-
-        final long token = Binder.clearCallingIdentity();
+        AppSupportedLocalesChangedAtomRecord atomRecord = new AppSupportedLocalesChangedAtomRecord(
+                Binder.getCallingUid());
         try {
-            setOverrideLocaleConfigUnchecked(appPackageName, userId, localeConfig);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
+            requireNonNull(appPackageName);
 
-        //TODO: Add metrics to monitor the usage by applications
+            //Allow apps with INTERACT_ACROSS_USERS permission to set locales for different user.
+            userId = mActivityManagerInternal.handleIncomingUser(
+                    Binder.getCallingPid(), Binder.getCallingUid(), userId,
+                    false /* allowAll */, ActivityManagerInternal.ALLOW_NON_FULL,
+                    "setOverrideLocaleConfig", /* callerPackage= */ null);
+
+            // This function handles two types of set operations:
+            // 1.) A normal, an app overrides its own LocaleConfig.
+            // 2.) A privileged system application or service is granted the necessary permission to
+            // override a LocaleConfig of another package.
+            if (!isPackageOwnedByCaller(appPackageName, userId, null, atomRecord)) {
+                enforceSetAppSpecificLocaleConfigPermission(atomRecord);
+            }
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                setOverrideLocaleConfigUnchecked(appPackageName, userId, localeConfig, atomRecord);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        } finally {
+            logAppSupportedLocalesChangedMetric(atomRecord);
+        }
     }
+
     private void setOverrideLocaleConfigUnchecked(@NonNull String appPackageName,
-            @UserIdInt int userId, @Nullable LocaleConfig overridelocaleConfig) {
+            @UserIdInt int userId, @Nullable LocaleConfig overridelocaleConfig,
+            @NonNull AppSupportedLocalesChangedAtomRecord atomRecord) {
         synchronized (mWriteLock) {
             if (DEBUG) {
                 Slog.d(TAG,
@@ -609,8 +613,18 @@
                     Slog.d(TAG, "remove the override LocaleConfig");
                     file.delete();
                 }
+                atomRecord.setOverrideRemoved(true);
+                atomRecord.setStatus(FrameworkStatsLog
+                        .APP_SUPPORTED_LOCALES_CHANGED__STATUS__SUCCESS);
                 return;
             } else {
+                if (overridelocaleConfig.isSameLocaleConfig(
+                        getOverrideLocaleConfig(appPackageName, userId))) {
+                    Slog.d(TAG, "the same override, ignore it");
+                    atomRecord.setSameAsPrevConfig(true);
+                    return;
+                }
+
                 LocaleList localeList = overridelocaleConfig.getSupportedLocales();
                 // Normally the LocaleList object should not be null. However we reassign it as the
                 // empty list in case it happens.
@@ -621,6 +635,7 @@
                     Slog.d(TAG,
                             "setOverrideLocaleConfig, localeList: " + localeList.toLanguageTags());
                 }
+                atomRecord.setNumLocales(localeList.size());
 
                 // Store the override LocaleConfig to the file storage.
                 final AtomicFile atomicFile = new AtomicFile(file);
@@ -633,11 +648,25 @@
                     if (stream != null) {
                         atomicFile.failWrite(stream);
                     }
+                    atomRecord.setStatus(FrameworkStatsLog
+                            .APP_SUPPORTED_LOCALES_CHANGED__STATUS__FAILURE_WRITE_TO_STORAGE);
                     return;
                 }
                 atomicFile.finishWrite(stream);
                 // Clear per-app locales if they are not in the override LocaleConfig.
                 removeUnsupportedAppLocales(appPackageName, userId, overridelocaleConfig);
+                try {
+                    Context appContext = mContext.createPackageContext(appPackageName, 0);
+                    if (overridelocaleConfig.isSameLocaleConfig(
+                            LocaleConfig.fromContextIgnoringOverride(appContext))) {
+                        Slog.d(TAG, "setOverrideLocaleConfig, same as the app's LocaleConfig");
+                        atomRecord.setSameAsResConfig(true);
+                    }
+                } catch (PackageManager.NameNotFoundException e) {
+                    Slog.e(TAG, "Unknown package name " + appPackageName);
+                }
+                atomRecord.setStatus(FrameworkStatsLog
+                        .APP_SUPPORTED_LOCALES_CHANGED__STATUS__SUCCESS);
                 if (DEBUG) {
                     Slog.i(TAG, "Successfully written to " + atomicFile);
                 }
@@ -677,10 +706,17 @@
         }
     }
 
-    private void enforceSetAppSpecificLocaleConfigPermission() {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.SET_APP_SPECIFIC_LOCALECONFIG,
-                "setOverrideLocaleConfig");
+    private void enforceSetAppSpecificLocaleConfigPermission(
+            AppSupportedLocalesChangedAtomRecord atomRecord) {
+        try {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.SET_APP_SPECIFIC_LOCALECONFIG,
+                    "setOverrideLocaleConfig");
+        } catch (SecurityException e) {
+            atomRecord.setStatus(FrameworkStatsLog
+                    .APP_SUPPORTED_LOCALES_CHANGED__STATUS__FAILURE_PERMISSION_ABSENT);
+            throw e;
+        }
     }
 
     /**
@@ -796,4 +832,16 @@
         final File dir = new File(Environment.getDataSystemDeDirectory(userId), LOCALE_CONFIGS);
         return new File(dir, appPackageName + SUFFIX_FILE_NAME);
     }
+
+    private void logAppSupportedLocalesChangedMetric(
+            @NonNull AppSupportedLocalesChangedAtomRecord atomRecord) {
+        FrameworkStatsLog.write(FrameworkStatsLog.APP_SUPPORTED_LOCALES_CHANGED,
+                atomRecord.mCallingUid,
+                atomRecord.mTargetUid,
+                atomRecord.mNumLocales,
+                atomRecord.mOverrideRemoved,
+                atomRecord.mSameAsResConfig,
+                atomRecord.mSameAsPrevConfig,
+                atomRecord.mStatus);
+    }
 }
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 4013468..5a832b7 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -420,7 +420,7 @@
         try (LockscreenCredential unifiedProfilePassword = generateRandomProfilePassword()) {
             setLockCredentialInternal(unifiedProfilePassword, profileUserPassword, profileUserId,
                     /* isLockTiedToParent= */ true);
-            tieProfileLockToParent(profileUserId, unifiedProfilePassword);
+            tieProfileLockToParent(profileUserId, parentId, unifiedProfilePassword);
             mManagedProfilePasswordCache.storePassword(profileUserId, unifiedProfilePassword);
         }
     }
@@ -1065,18 +1065,7 @@
         mContext.enforceCallingOrSelfPermission(PERMISSION, "LockSettingsHave");
     }
 
-    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,
-    };
-
     private final void checkDatabaseReadPermission(String requestedKey, int userId) {
-        if (ArrayUtils.contains(UNPROTECTED_SETTINGS, requestedKey)) {
-            return;
-        }
         if (!hasPermission(PERMISSION)) {
             throw new SecurityException("uid=" + getCallingUid() + " needs permission "
                     + PERMISSION + " to read " + requestedKey + " for user " + userId);
@@ -1190,9 +1179,6 @@
     @Override
     public boolean getBoolean(String key, boolean defaultValue, int userId) {
         checkDatabaseReadPermission(key, userId);
-        if (Settings.Secure.LOCK_PATTERN_ENABLED.equals(key)) {
-            return getCredentialTypeInternal(userId) == CREDENTIAL_TYPE_PATTERN;
-        }
         return mStorage.getBoolean(key, defaultValue, userId);
     }
 
@@ -1887,34 +1873,43 @@
     }
 
     @VisibleForTesting /** Note: this method is overridden in unit tests */
-    protected void tieProfileLockToParent(int userId, LockscreenCredential password) {
-        if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + userId);
+    protected void tieProfileLockToParent(int profileUserId, int parentUserId,
+            LockscreenCredential password) {
+        if (DEBUG) Slog.v(TAG, "tieProfileLockToParent for user: " + profileUserId);
         final byte[] iv;
         final byte[] ciphertext;
+        final long parentSid;
+        try {
+            parentSid = getGateKeeperService().getSecureUserId(parentUserId);
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Failed to talk to GateKeeper service", e);
+        }
+
         try {
             KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES);
             keyGenerator.init(new SecureRandom());
             SecretKey secretKey = keyGenerator.generateKey();
             try {
                 mJavaKeyStore.setEntry(
-                        PROFILE_KEY_NAME_ENCRYPT + userId,
+                        PROFILE_KEY_NAME_ENCRYPT + profileUserId,
                         new java.security.KeyStore.SecretKeyEntry(secretKey),
                         new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT)
                                 .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                                 .build());
                 mJavaKeyStore.setEntry(
-                        PROFILE_KEY_NAME_DECRYPT + userId,
+                        PROFILE_KEY_NAME_DECRYPT + profileUserId,
                         new java.security.KeyStore.SecretKeyEntry(secretKey),
                         new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
                                 .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
                                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
                                 .setUserAuthenticationRequired(true)
+                                .setBoundToSpecificSecureUserId(parentSid)
                                 .setUserAuthenticationValidityDurationSeconds(30)
                                 .build());
                 // Key imported, obtain a reference to it.
                 SecretKey keyStoreEncryptionKey = (SecretKey) mJavaKeyStore.getKey(
-                        PROFILE_KEY_NAME_ENCRYPT + userId, null);
+                        PROFILE_KEY_NAME_ENCRYPT + profileUserId, null);
                 Cipher cipher = Cipher.getInstance(
                         KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_GCM + "/"
                                 + KeyProperties.ENCRYPTION_PADDING_NONE);
@@ -1923,7 +1918,7 @@
                 iv = cipher.getIV();
             } finally {
                 // The original key can now be discarded.
-                mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + userId);
+                mJavaKeyStore.deleteEntry(PROFILE_KEY_NAME_ENCRYPT + profileUserId);
             }
         } catch (UnrecoverableKeyException
                 | BadPaddingException | IllegalBlockSizeException | KeyStoreException
@@ -1933,7 +1928,7 @@
         if (iv.length != PROFILE_KEY_IV_SIZE) {
             throw new IllegalArgumentException("Invalid iv length: " + iv.length);
         }
-        mStorage.writeChildProfileLock(userId, ArrayUtils.concat(iv, ciphertext));
+        mStorage.writeChildProfileLock(profileUserId, ArrayUtils.concat(iv, ciphertext));
     }
 
     private void setUserKeyProtection(@UserIdInt int userId, byte[] secret) {
@@ -2045,7 +2040,7 @@
                 LockscreenCredential piUserDecryptedPassword = profileUserDecryptedPasswords.get(i);
                 if (piUserId != -1 && piUserDecryptedPassword != null) {
                     if (DEBUG) Slog.v(TAG, "Restore tied profile lock");
-                    tieProfileLockToParent(piUserId, piUserDecryptedPassword);
+                    tieProfileLockToParent(piUserId, userId, piUserDecryptedPassword);
                 }
                 if (piUserDecryptedPassword != null) {
                     piUserDecryptedPassword.zeroize();
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index e592a22..d070b41 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -780,6 +780,10 @@
         int slot = loadWeaverSlot(protectorId, userId);
         destroyState(WEAVER_SLOT_NAME, protectorId, userId);
         if (slot != INVALID_WEAVER_SLOT) {
+            if (!isWeaverAvailable()) {
+                Slog.e(TAG, "Cannot erase Weaver slot because Weaver is unavailable");
+                return;
+            }
             Set<Integer> usedSlots = getUsedWeaverSlots();
             if (!usedSlots.contains(slot)) {
                 Slog.i(TAG, "Destroy weaver slot " + slot + " for user " + userId);
diff --git a/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java b/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
new file mode 100644
index 0000000..eb997ba
--- /dev/null
+++ b/services/core/java/com/android/server/media/AudioPoliciesBluetoothRouteController.java
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_AUDIO;
+import static android.bluetooth.BluetoothAdapter.STATE_CONNECTED;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothProfile;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.media.AudioManager;
+import android.media.AudioSystem;
+import android.media.MediaRoute2Info;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Controls bluetooth routes and provides selected route override.
+ *
+ * <p>The controller offers similar functionality to {@link LegacyBluetoothRouteController} but does
+ * not support routes selection logic. Instead, relies on external clients to make a decision
+ * about currently selected route.
+ *
+ * <p>Selected route override should be used by {@link AudioManager} which is aware of Audio
+ * Policies.
+ */
+/* package */ class AudioPoliciesBluetoothRouteController
+        implements BluetoothRouteController {
+    private static final String TAG = "APBtRouteController";
+
+    private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
+    private static final String LE_AUDIO_ROUTE_ID_PREFIX = "LE_AUDIO_";
+
+    @NonNull
+    private final AdapterStateChangedReceiver mAdapterStateChangedReceiver =
+            new AdapterStateChangedReceiver();
+
+    @NonNull
+    private final DeviceStateChangedReceiver mDeviceStateChangedReceiver =
+            new DeviceStateChangedReceiver();
+
+    @NonNull
+    private final Map<String, BluetoothRouteInfo> mBluetoothRoutes = new HashMap<>();
+
+    @NonNull
+    private final SparseIntArray mVolumeMap = new SparseIntArray();
+
+    @NonNull
+    private final Context mContext;
+    @NonNull
+    private final BluetoothAdapter mBluetoothAdapter;
+    @NonNull
+    private final BluetoothRouteController.BluetoothRoutesUpdatedListener mListener;
+    @NonNull
+    private final BluetoothProfileMonitor mBluetoothProfileMonitor;
+    @NonNull
+    private final AudioManager mAudioManager;
+
+    @Nullable
+    private BluetoothRouteInfo mSelectedBluetoothRoute;
+
+    AudioPoliciesBluetoothRouteController(@NonNull Context context,
+            @NonNull BluetoothAdapter bluetoothAdapter,
+            @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) {
+        this(context, bluetoothAdapter,
+                new BluetoothProfileMonitor(context, bluetoothAdapter), listener);
+    }
+
+    @VisibleForTesting
+    AudioPoliciesBluetoothRouteController(@NonNull Context context,
+            @NonNull BluetoothAdapter bluetoothAdapter,
+            @NonNull BluetoothProfileMonitor bluetoothProfileMonitor,
+            @NonNull BluetoothRouteController.BluetoothRoutesUpdatedListener listener) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(bluetoothAdapter);
+        Objects.requireNonNull(bluetoothProfileMonitor);
+        Objects.requireNonNull(listener);
+
+        mContext = context;
+        mBluetoothAdapter = bluetoothAdapter;
+        mBluetoothProfileMonitor = bluetoothProfileMonitor;
+        mAudioManager = mContext.getSystemService(AudioManager.class);
+        mListener = listener;
+
+        updateBluetoothRoutes();
+    }
+
+    @Override
+    public void start(UserHandle user) {
+        mBluetoothProfileMonitor.start();
+
+        IntentFilter adapterStateChangedIntentFilter = new IntentFilter();
+
+        adapterStateChangedIntentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+        mContext.registerReceiverAsUser(mAdapterStateChangedReceiver, user,
+                adapterStateChangedIntentFilter, null, null);
+
+        IntentFilter deviceStateChangedIntentFilter = new IntentFilter();
+
+        deviceStateChangedIntentFilter.addAction(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
+        deviceStateChangedIntentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
+        deviceStateChangedIntentFilter.addAction(BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED);
+        deviceStateChangedIntentFilter.addAction(
+                BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED);
+        deviceStateChangedIntentFilter.addAction(
+                BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED);
+        deviceStateChangedIntentFilter.addAction(
+                BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED);
+
+        mContext.registerReceiverAsUser(mDeviceStateChangedReceiver, user,
+                deviceStateChangedIntentFilter, null, null);
+    }
+
+    @Override
+    public void stop() {
+        mContext.unregisterReceiver(mAdapterStateChangedReceiver);
+        mContext.unregisterReceiver(mDeviceStateChangedReceiver);
+    }
+
+    @Override
+    public boolean selectRoute(@Nullable String deviceAddress) {
+        synchronized (this) {
+            // Fetch all available devices in order to avoid race conditions with Bluetooth stack.
+            updateBluetoothRoutes();
+
+            if (deviceAddress == null) {
+                mSelectedBluetoothRoute = null;
+                return true;
+            }
+
+            BluetoothRouteInfo bluetoothRouteInfo = mBluetoothRoutes.get(deviceAddress);
+
+            if (bluetoothRouteInfo == null) {
+                Slog.w(TAG, "Cannot find bluetooth route for " + deviceAddress);
+                return false;
+            }
+
+            mSelectedBluetoothRoute = bluetoothRouteInfo;
+            setRouteConnectionState(mSelectedBluetoothRoute, STATE_CONNECTED);
+
+            updateConnectivityStateForDevicesInTheSameGroup();
+
+            return true;
+        }
+    }
+
+    /**
+     * Updates connectivity state for devices in the same devices group.
+     *
+     * <p>{@link BluetoothProfile#LE_AUDIO} and {@link BluetoothProfile#HEARING_AID} support
+     * grouping devices. Devices that belong to the same group should have the same routeId but
+     * different physical address.
+     *
+     * <p>In case one of the devices from the group is selected then other devices should also
+     * reflect this by changing their connectivity status to
+     * {@link MediaRoute2Info#CONNECTION_STATE_CONNECTED}.
+     */
+    private void updateConnectivityStateForDevicesInTheSameGroup() {
+        synchronized (this) {
+            for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
+                if (TextUtils.equals(btRoute.mRoute.getId(), mSelectedBluetoothRoute.mRoute.getId())
+                        && !TextUtils.equals(btRoute.mBtDevice.getAddress(),
+                        mSelectedBluetoothRoute.mBtDevice.getAddress())) {
+                    setRouteConnectionState(btRoute, STATE_CONNECTED);
+                }
+            }
+        }
+    }
+
+    @Override
+    public void transferTo(@Nullable String routeId) {
+        if (routeId == null) {
+            mBluetoothAdapter.removeActiveDevice(ACTIVE_DEVICE_AUDIO);
+            return;
+        }
+
+        BluetoothRouteInfo btRouteInfo = findBluetoothRouteWithRouteId(routeId);
+
+        if (btRouteInfo == null) {
+            Slog.w(TAG, "transferTo: Unknown route. ID=" + routeId);
+            return;
+        }
+
+        mBluetoothAdapter.setActiveDevice(btRouteInfo.mBtDevice, ACTIVE_DEVICE_AUDIO);
+    }
+
+    @Nullable
+    private BluetoothRouteInfo findBluetoothRouteWithRouteId(@Nullable String routeId) {
+        if (routeId == null) {
+            return null;
+        }
+        synchronized (this) {
+            for (BluetoothRouteInfo btRouteInfo : mBluetoothRoutes.values()) {
+                if (TextUtils.equals(btRouteInfo.mRoute.getId(), routeId)) {
+                    return btRouteInfo;
+                }
+            }
+        }
+        return null;
+    }
+
+    private void updateBluetoothRoutes() {
+        Set<BluetoothDevice> bondedDevices = mBluetoothAdapter.getBondedDevices();
+
+        if (bondedDevices == null) {
+            return;
+        }
+
+        synchronized (this) {
+            mBluetoothRoutes.clear();
+
+            // We need to query all available to BT stack devices in order to avoid inconsistency
+            // between external services, like, AndroidManager, and BT stack.
+            for (BluetoothDevice device : bondedDevices) {
+                if (isDeviceConnected(device)) {
+                    BluetoothRouteInfo newBtRoute = createBluetoothRoute(device);
+                    if (newBtRoute.mConnectedProfiles.size() > 0) {
+                        mBluetoothRoutes.put(device.getAddress(), newBtRoute);
+                    }
+                }
+            }
+        }
+    }
+
+    @VisibleForTesting
+        /* package */ boolean isDeviceConnected(@NonNull BluetoothDevice device) {
+        return device.isConnected();
+    }
+
+    @Nullable
+    @Override
+    public MediaRoute2Info getSelectedRoute() {
+        synchronized (this) {
+            if (mSelectedBluetoothRoute == null) {
+                return null;
+            }
+
+            return mSelectedBluetoothRoute.mRoute;
+        }
+    }
+
+    @NonNull
+    @Override
+    public List<MediaRoute2Info> getTransferableRoutes() {
+        List<MediaRoute2Info> routes = getAllBluetoothRoutes();
+        synchronized (this) {
+            if (mSelectedBluetoothRoute != null) {
+                routes.remove(mSelectedBluetoothRoute.mRoute);
+            }
+        }
+        return routes;
+    }
+
+    @NonNull
+    @Override
+    public List<MediaRoute2Info> getAllBluetoothRoutes() {
+        List<MediaRoute2Info> routes = new ArrayList<>();
+        List<String> routeIds = new ArrayList<>();
+
+        MediaRoute2Info selectedRoute = getSelectedRoute();
+        if (selectedRoute != null) {
+            routes.add(selectedRoute);
+            routeIds.add(selectedRoute.getId());
+        }
+
+        synchronized (this) {
+            for (BluetoothRouteInfo btRoute : mBluetoothRoutes.values()) {
+                // A pair of hearing aid devices or having the same hardware address
+                if (routeIds.contains(btRoute.mRoute.getId())) {
+                    continue;
+                }
+                routes.add(btRoute.mRoute);
+                routeIds.add(btRoute.mRoute.getId());
+            }
+        }
+        return routes;
+    }
+
+    @Override
+    public boolean updateVolumeForDevices(int devices, int volume) {
+        int routeType;
+        if ((devices & (AudioSystem.DEVICE_OUT_HEARING_AID)) != 0) {
+            routeType = MediaRoute2Info.TYPE_HEARING_AID;
+        } else if ((devices & (AudioManager.DEVICE_OUT_BLUETOOTH_A2DP
+                | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
+                | AudioManager.DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) != 0) {
+            routeType = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+        } else if ((devices & (AudioManager.DEVICE_OUT_BLE_HEADSET)) != 0) {
+            routeType = MediaRoute2Info.TYPE_BLE_HEADSET;
+        } else {
+            return false;
+        }
+
+        synchronized (this) {
+            mVolumeMap.put(routeType, volume);
+            if (mSelectedBluetoothRoute == null
+                    || mSelectedBluetoothRoute.mRoute.getType() != routeType) {
+                return false;
+            }
+
+            mSelectedBluetoothRoute.mRoute =
+                    new MediaRoute2Info.Builder(mSelectedBluetoothRoute.mRoute)
+                            .setVolume(volume)
+                            .build();
+        }
+
+        notifyBluetoothRoutesUpdated();
+        return true;
+    }
+
+    private void notifyBluetoothRoutesUpdated() {
+        mListener.onBluetoothRoutesUpdated(getAllBluetoothRoutes());
+    }
+
+    private BluetoothRouteInfo createBluetoothRoute(BluetoothDevice device) {
+        BluetoothRouteInfo
+                newBtRoute = new BluetoothRouteInfo();
+        newBtRoute.mBtDevice = device;
+
+        String routeId = device.getAddress();
+        String deviceName = device.getName();
+        if (TextUtils.isEmpty(deviceName)) {
+            deviceName = mContext.getResources().getText(R.string.unknownName).toString();
+        }
+        int type = MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+        newBtRoute.mConnectedProfiles = new SparseBooleanArray();
+        if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.A2DP, device)) {
+            newBtRoute.mConnectedProfiles.put(BluetoothProfile.A2DP, true);
+        }
+        if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.HEARING_AID, device)) {
+            newBtRoute.mConnectedProfiles.put(BluetoothProfile.HEARING_AID, true);
+            // Intentionally assign the same ID for a pair of devices to publish only one of them.
+            routeId = HEARING_AID_ROUTE_ID_PREFIX
+                    + mBluetoothProfileMonitor.getGroupId(BluetoothProfile.HEARING_AID, device);
+            type = MediaRoute2Info.TYPE_HEARING_AID;
+        }
+        if (mBluetoothProfileMonitor.isProfileSupported(BluetoothProfile.LE_AUDIO, device)) {
+            newBtRoute.mConnectedProfiles.put(BluetoothProfile.LE_AUDIO, true);
+            routeId = LE_AUDIO_ROUTE_ID_PREFIX
+                    + mBluetoothProfileMonitor.getGroupId(BluetoothProfile.LE_AUDIO, device);
+            type = MediaRoute2Info.TYPE_BLE_HEADSET;
+        }
+
+        // Current volume will be set when connected.
+        newBtRoute.mRoute = new MediaRoute2Info.Builder(routeId, deviceName)
+                .addFeature(MediaRoute2Info.FEATURE_LIVE_AUDIO)
+                .addFeature(MediaRoute2Info.FEATURE_LOCAL_PLAYBACK)
+                .setConnectionState(MediaRoute2Info.CONNECTION_STATE_DISCONNECTED)
+                .setDescription(mContext.getResources().getText(
+                        R.string.bluetooth_a2dp_audio_route_name).toString())
+                .setType(type)
+                .setVolumeHandling(MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+                .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+                .setAddress(device.getAddress())
+                .build();
+        return newBtRoute;
+    }
+
+    private void setRouteConnectionState(@NonNull BluetoothRouteInfo btRoute,
+            @MediaRoute2Info.ConnectionState int state) {
+        if (btRoute == null) {
+            Slog.w(TAG, "setRouteConnectionState: route shouldn't be null");
+            return;
+        }
+        if (btRoute.mRoute.getConnectionState() == state) {
+            return;
+        }
+
+        MediaRoute2Info.Builder builder = new MediaRoute2Info.Builder(btRoute.mRoute)
+                .setConnectionState(state);
+        builder.setType(btRoute.getRouteType());
+
+
+
+        if (state == MediaRoute2Info.CONNECTION_STATE_CONNECTED) {
+            int currentVolume;
+            synchronized (this) {
+                currentVolume = mVolumeMap.get(btRoute.getRouteType(), 0);
+            }
+            builder.setVolume(currentVolume);
+        }
+
+        btRoute.mRoute = builder.build();
+    }
+
+    private static class BluetoothRouteInfo {
+        private BluetoothDevice mBtDevice;
+        private MediaRoute2Info mRoute;
+        private SparseBooleanArray mConnectedProfiles;
+
+        @MediaRoute2Info.Type
+        int getRouteType() {
+            // Let hearing aid profile have a priority.
+            if (mConnectedProfiles.get(BluetoothProfile.HEARING_AID, false)) {
+                return MediaRoute2Info.TYPE_HEARING_AID;
+            }
+
+            if (mConnectedProfiles.get(BluetoothProfile.LE_AUDIO, false)) {
+                return MediaRoute2Info.TYPE_BLE_HEADSET;
+            }
+
+            return MediaRoute2Info.TYPE_BLUETOOTH_A2DP;
+        }
+    }
+
+    private class AdapterStateChangedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
+            if (state == BluetoothAdapter.STATE_OFF
+                    || state == BluetoothAdapter.STATE_TURNING_OFF) {
+                synchronized (AudioPoliciesBluetoothRouteController.this) {
+                    mBluetoothRoutes.clear();
+                }
+                notifyBluetoothRoutesUpdated();
+            } else if (state == BluetoothAdapter.STATE_ON) {
+                updateBluetoothRoutes();
+
+                boolean shouldCallListener;
+                synchronized (AudioPoliciesBluetoothRouteController.this) {
+                    shouldCallListener = !mBluetoothRoutes.isEmpty();
+                }
+
+                if (shouldCallListener) {
+                    notifyBluetoothRoutesUpdated();
+                }
+            }
+        }
+    }
+
+    private class DeviceStateChangedReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch (intent.getAction()) {
+                case BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED:
+                case BluetoothHearingAid.ACTION_ACTIVE_DEVICE_CHANGED:
+                case BluetoothLeAudio.ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED:
+                case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
+                case BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED:
+                case BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED:
+                    updateBluetoothRoutes();
+                    notifyBluetoothRoutesUpdated();
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/media/BluetoothProfileMonitor.java b/services/core/java/com/android/server/media/BluetoothProfileMonitor.java
new file mode 100644
index 0000000..b129dd0
--- /dev/null
+++ b/services/core/java/com/android/server/media/BluetoothProfileMonitor.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 com.android.server.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import java.util.Objects;
+
+/* package */ class BluetoothProfileMonitor {
+
+    /* package */ static final long GROUP_ID_NO_GROUP = -1L;
+
+    @NonNull
+    private final ProfileListener mProfileListener = new ProfileListener();
+
+    @NonNull
+    private final Context mContext;
+    @NonNull
+    private final BluetoothAdapter mBluetoothAdapter;
+
+    @Nullable
+    private BluetoothA2dp mA2dpProfile;
+    @Nullable
+    private BluetoothHearingAid mHearingAidProfile;
+    @Nullable
+    private BluetoothLeAudio mLeAudioProfile;
+
+    @Nullable
+    private OnProfileChangedListener mOnProfileChangedListener;
+
+    BluetoothProfileMonitor(@NonNull Context context,
+            @NonNull BluetoothAdapter bluetoothAdapter) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(bluetoothAdapter);
+
+        mContext = context;
+        mBluetoothAdapter = bluetoothAdapter;
+    }
+
+    /* package */ synchronized void setOnProfileChangedListener(
+            @NonNull OnProfileChangedListener listener) {
+        mOnProfileChangedListener = listener;
+    }
+
+    /* package */ void start() {
+        mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.A2DP);
+        mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEARING_AID);
+        mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.LE_AUDIO);
+    }
+
+    /* package */ boolean isProfileSupported(int profile, @NonNull BluetoothDevice device) {
+        BluetoothProfile bluetoothProfile;
+
+        synchronized (this) {
+            switch (profile) {
+                case BluetoothProfile.A2DP:
+                    bluetoothProfile = mA2dpProfile;
+                    break;
+                case BluetoothProfile.LE_AUDIO:
+                    bluetoothProfile = mLeAudioProfile;
+                    break;
+                case BluetoothProfile.HEARING_AID:
+                    bluetoothProfile = mHearingAidProfile;
+                    break;
+                default:
+                    throw new IllegalArgumentException(profile
+                            + " is not supported as Bluetooth profile");
+            }
+        }
+
+        if (bluetoothProfile == null) {
+            return false;
+        }
+
+        return bluetoothProfile.getConnectedDevices().contains(device);
+    }
+
+    /* package */ long getGroupId(int profile, @NonNull BluetoothDevice device) {
+        synchronized (this) {
+            switch (profile) {
+                case BluetoothProfile.A2DP:
+                    return GROUP_ID_NO_GROUP;
+                case BluetoothProfile.LE_AUDIO:
+                    return mLeAudioProfile == null ? GROUP_ID_NO_GROUP : mLeAudioProfile.getGroupId(
+                            device);
+                case BluetoothProfile.HEARING_AID:
+                    return mHearingAidProfile == null
+                            ? GROUP_ID_NO_GROUP : mHearingAidProfile.getHiSyncId(device);
+                default:
+                    throw new IllegalArgumentException(profile
+                            + " is not supported as Bluetooth profile");
+            }
+        }
+    }
+
+    /* package */ interface OnProfileChangedListener {
+        void onProfileChange(int profile);
+    }
+
+    private final class ProfileListener implements BluetoothProfile.ServiceListener {
+        @Override
+        public void onServiceConnected(int profile, BluetoothProfile proxy) {
+            OnProfileChangedListener listener;
+
+            synchronized (BluetoothProfileMonitor.this) {
+                switch (profile) {
+                    case BluetoothProfile.A2DP:
+                        mA2dpProfile = (BluetoothA2dp) proxy;
+                        break;
+                    case BluetoothProfile.HEARING_AID:
+                        mHearingAidProfile = (BluetoothHearingAid) proxy;
+                        break;
+                    case BluetoothProfile.LE_AUDIO:
+                        mLeAudioProfile = (BluetoothLeAudio) proxy;
+                        break;
+                    default:
+                        return;
+                }
+
+                listener = mOnProfileChangedListener;
+            }
+
+            if (listener != null) {
+                listener.onProfileChange(profile);
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(int profile) {
+            OnProfileChangedListener listener;
+
+            synchronized (BluetoothProfileMonitor.this) {
+                switch (profile) {
+                    case BluetoothProfile.A2DP:
+                        mA2dpProfile = null;
+                        break;
+                    case BluetoothProfile.HEARING_AID:
+                        mHearingAidProfile = null;
+                        break;
+                    case BluetoothProfile.LE_AUDIO:
+                        mLeAudioProfile = null;
+                        break;
+                    default:
+                        return;
+                }
+
+                listener = mOnProfileChangedListener;
+            }
+
+            if (listener != null) {
+                listener.onProfileChange(profile);
+            }
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/media/BluetoothRouteController.java b/services/core/java/com/android/server/media/BluetoothRouteController.java
index 08691d0..d4a1184 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteController.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteController.java
@@ -68,6 +68,17 @@
      */
     void stop();
 
+
+    /**
+     * Selects the route with the given {@code deviceAddress}.
+     *
+     * @param deviceAddress The physical address of the device to select. May be null to unselect
+     *                      the currently selected device.
+     * @return Whether the selection succeeds. If the selection fails, the state of the instance
+     * remains unaltered.
+     */
+    boolean selectRoute(@Nullable String deviceAddress);
+
     /**
      * Transfers Bluetooth output to the given route.
      *
@@ -145,6 +156,12 @@
         }
 
         @Override
+        public boolean selectRoute(String deviceAddress) {
+            // no op
+            return false;
+        }
+
+        @Override
         public void transferTo(String routeId) {
             // no op
         }
diff --git a/services/core/java/com/android/server/media/DeviceRouteController.java b/services/core/java/com/android/server/media/DeviceRouteController.java
new file mode 100644
index 0000000..8bd6416
--- /dev/null
+++ b/services/core/java/com/android/server/media/DeviceRouteController.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
+import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
+import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
+import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
+import static android.media.MediaRoute2Info.TYPE_DOCK;
+import static android.media.MediaRoute2Info.TYPE_HDMI;
+import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
+import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.IAudioService;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Objects;
+
+/**
+ * Controls device routes.
+ *
+ * <p>A device route is a system wired route, for example, built-in speaker, wired
+ * headsets and headphones, dock, hdmi, or usb devices.
+ *
+ * <p>Thread safe.
+ *
+ * @see SystemMediaRoute2Provider
+ */
+/* package */ final class DeviceRouteController {
+
+    private static final String TAG = "WiredRoutesController";
+
+    private static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
+
+    @NonNull
+    private final Context mContext;
+    @NonNull
+    private final AudioManager mAudioManager;
+    @NonNull
+    private final IAudioService mAudioService;
+
+    @NonNull
+    private final OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+    @NonNull
+    private final AudioRoutesObserver mAudioRoutesObserver = new AudioRoutesObserver();
+
+    private int mDeviceVolume;
+    private MediaRoute2Info mDeviceRoute;
+
+    /* package */ static DeviceRouteController createInstance(@NonNull Context context,
+            @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+        AudioManager audioManager = context.getSystemService(AudioManager.class);
+        IAudioService audioService = IAudioService.Stub.asInterface(
+                ServiceManager.getService(Context.AUDIO_SERVICE));
+
+        return new DeviceRouteController(context,
+                audioManager,
+                audioService,
+                onDeviceRouteChangedListener);
+    }
+
+    @VisibleForTesting
+    /* package */ DeviceRouteController(@NonNull Context context,
+            @NonNull AudioManager audioManager,
+            @NonNull IAudioService audioService,
+            @NonNull OnDeviceRouteChangedListener onDeviceRouteChangedListener) {
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(audioManager);
+        Objects.requireNonNull(audioService);
+        Objects.requireNonNull(onDeviceRouteChangedListener);
+
+        mContext = context;
+        mOnDeviceRouteChangedListener = onDeviceRouteChangedListener;
+
+        mAudioManager = audioManager;
+        mAudioService = audioService;
+
+        AudioRoutesInfo newAudioRoutes = null;
+        try {
+            newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Cannot connect to audio service to start listen to routes", e);
+        }
+
+        mDeviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+    }
+
+    @NonNull
+    /* package */ synchronized MediaRoute2Info getDeviceRoute() {
+        return mDeviceRoute;
+    }
+
+    /* package */ synchronized boolean updateVolume(int volume) {
+        if (mDeviceVolume == volume) {
+            return false;
+        }
+
+        mDeviceVolume = volume;
+        mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
+                .setVolume(volume)
+                .build();
+
+        return true;
+    }
+
+    private MediaRoute2Info createRouteFromAudioInfo(@Nullable AudioRoutesInfo newRoutes) {
+        int name = R.string.default_audio_route_name;
+        int type = TYPE_BUILTIN_SPEAKER;
+
+        if (newRoutes != null) {
+            if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
+                type = TYPE_WIRED_HEADPHONES;
+                name = com.android.internal.R.string.default_audio_route_name_headphones;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
+                type = TYPE_WIRED_HEADSET;
+                name = com.android.internal.R.string.default_audio_route_name_headphones;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
+                type = TYPE_DOCK;
+                name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
+                type = TYPE_HDMI;
+                name = com.android.internal.R.string.default_audio_route_name_external_device;
+            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
+                type = TYPE_USB_DEVICE;
+                name = com.android.internal.R.string.default_audio_route_name_usb;
+            }
+        }
+
+        synchronized (this) {
+            return new MediaRoute2Info.Builder(
+                    DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
+                    .setVolumeHandling(mAudioManager.isVolumeFixed()
+                            ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
+                            : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
+                    .setVolume(mDeviceVolume)
+                    .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
+                    .setType(type)
+                    .addFeature(FEATURE_LIVE_AUDIO)
+                    .addFeature(FEATURE_LIVE_VIDEO)
+                    .addFeature(FEATURE_LOCAL_PLAYBACK)
+                    .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
+                    .build();
+        }
+    }
+
+    private void notifyDeviceRouteUpdate(@NonNull MediaRoute2Info deviceRoute) {
+        mOnDeviceRouteChangedListener.onDeviceRouteChanged(deviceRoute);
+    }
+
+    /* package */ interface OnDeviceRouteChangedListener {
+        void onDeviceRouteChanged(@NonNull MediaRoute2Info deviceRoute);
+    }
+
+    private class AudioRoutesObserver extends IAudioRoutesObserver.Stub {
+
+        @Override
+        public void dispatchAudioRoutesChanged(AudioRoutesInfo newAudioRoutes) {
+            MediaRoute2Info deviceRoute = createRouteFromAudioInfo(newAudioRoutes);
+            synchronized (DeviceRouteController.this) {
+                mDeviceRoute = deviceRoute;
+            }
+            notifyDeviceRouteUpdate(deviceRoute);
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java b/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
index 7979d2a..e31a7fc 100644
--- a/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
+++ b/services/core/java/com/android/server/media/LegacyBluetoothRouteController.java
@@ -52,7 +52,7 @@
 import java.util.Set;
 
 class LegacyBluetoothRouteController implements BluetoothRouteController {
-    private static final String TAG = "BTRouteProvider";
+    private static final String TAG = "LBtRouteProvider";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final String HEARING_AID_ROUTE_ID_PREFIX = "HEARING_AID_";
@@ -132,6 +132,12 @@
         mContext.unregisterReceiver(mDeviceStateChangedReceiver);
     }
 
+    @Override
+    public boolean selectRoute(String deviceAddress) {
+        // No-op as the class decides if a route is selected based on Bluetooth events.
+        return false;
+    }
+
     /**
      * Transfers to a given bluetooth route.
      * The dedicated BT device with the route would be activated.
diff --git a/services/core/java/com/android/server/media/MediaFeatureFlagManager.java b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
new file mode 100644
index 0000000..723cda0
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaFeatureFlagManager.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import android.annotation.StringDef;
+import android.provider.DeviceConfig;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/* package */ class MediaFeatureFlagManager {
+
+    /**
+     * Namespace for media better together features.
+     */
+    private static final String NAMESPACE_MEDIA_BETTER_TOGETHER = "media_better_together";
+
+    @StringDef(prefix = "FEATURE_", value = {
+        FEATURE_IS_USING_LEGACY_BLUETOOTH_CONTROLLER
+    })
+    @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
+    @Retention(RetentionPolicy.SOURCE)
+    /* package */ @interface MediaFeatureFlag {}
+
+    /**
+     * Whether to use old legacy implementation of BluetoothRouteController or new
+     * 'Audio Strategies'-aware controller.
+     */
+    /* package */ static final @MediaFeatureFlag String
+            FEATURE_IS_USING_LEGACY_BLUETOOTH_CONTROLLER =
+            "BluetoothRouteController__enable_legacy_bluetooth_routes_controller";
+
+    private static final MediaFeatureFlagManager sInstance = new MediaFeatureFlagManager();
+
+    private MediaFeatureFlagManager() {
+        // Empty to prevent instantiation.
+    }
+
+    /* package */ MediaFeatureFlagManager getInstance() {
+        return sInstance;
+    }
+
+    /**
+     * Returns a boolean value from {@link DeviceConfig} from the system_time namespace, or
+     * {@code defaultValue} if there is no explicit value set.
+     */
+    public boolean getBoolean(@MediaFeatureFlag String key, boolean defaultValue) {
+        return DeviceConfig.getBoolean(NAMESPACE_MEDIA_BETTER_TOGETHER, key, defaultValue);
+    }
+}
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 76ff19f..638e81a 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -16,25 +16,12 @@
 
 package com.android.server.media;
 
-import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
-import static android.media.MediaRoute2Info.FEATURE_LIVE_VIDEO;
-import static android.media.MediaRoute2Info.FEATURE_LOCAL_PLAYBACK;
-import static android.media.MediaRoute2Info.TYPE_BUILTIN_SPEAKER;
-import static android.media.MediaRoute2Info.TYPE_DOCK;
-import static android.media.MediaRoute2Info.TYPE_HDMI;
-import static android.media.MediaRoute2Info.TYPE_USB_DEVICE;
-import static android.media.MediaRoute2Info.TYPE_WIRED_HEADPHONES;
-import static android.media.MediaRoute2Info.TYPE_WIRED_HEADSET;
-
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.media.AudioManager;
-import android.media.AudioRoutesInfo;
-import android.media.IAudioRoutesObserver;
-import android.media.IAudioService;
 import android.media.MediaRoute2Info;
 import android.media.MediaRoute2ProviderInfo;
 import android.media.MediaRoute2ProviderService;
@@ -43,14 +30,11 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
 
-import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 
 import java.util.Objects;
@@ -68,23 +52,21 @@
             SystemMediaRoute2Provider.class.getName());
 
     static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
-    static final String DEVICE_ROUTE_ID = "DEVICE_ROUTE";
     static final String SYSTEM_SESSION_ID = "SYSTEM_SESSION";
 
     private final AudioManager mAudioManager;
-    private final IAudioService mAudioService;
     private final Handler mHandler;
     private final Context mContext;
     private final UserHandle mUser;
+
+    private final DeviceRouteController mDeviceRouteController;
     private final BluetoothRouteController mBtRouteProvider;
 
     private String mSelectedRouteId;
     // For apps without MODIFYING_AUDIO_ROUTING permission.
     // This should be the currently selected route.
     MediaRoute2Info mDefaultRoute;
-    MediaRoute2Info mDeviceRoute;
     RoutingSessionInfo mDefaultSessionInfo;
-    int mDeviceVolume;
 
     private final AudioManagerBroadcastReceiver mAudioReceiver =
             new AudioManagerBroadcastReceiver();
@@ -93,19 +75,6 @@
     @GuardedBy("mRequestLock")
     private volatile SessionCreationRequest mPendingSessionCreationRequest;
 
-    final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
-        @Override
-        public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
-            mHandler.post(() -> {
-                updateDeviceRoute(newRoutes);
-                notifyProviderState();
-                if (updateSessionInfosIfNeeded()) {
-                    notifySessionInfoUpdated();
-                }
-            });
-        }
-    };
-
     SystemMediaRoute2Provider(Context context, UserHandle user) {
         super(COMPONENT_NAME);
         mIsSystemRouteProvider = true;
@@ -114,8 +83,6 @@
         mHandler = new Handler(Looper.getMainLooper());
 
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
-        mAudioService = IAudioService.Stub.asInterface(
-                ServiceManager.getService(Context.AUDIO_SERVICE));
 
         mBtRouteProvider = BluetoothRouteController.createInstance(context, (routes) -> {
             publishProviderState();
@@ -124,15 +91,18 @@
             }
         });
 
-        AudioRoutesInfo newAudioRoutes = null;
-        try {
-            newAudioRoutes = mAudioService.startWatchingRoutes(mAudioRoutesObserver);
-        } catch (RemoteException e) {
-        }
+        mDeviceRouteController = DeviceRouteController.createInstance(context, (deviceRoute) -> {
+            mHandler.post(() -> {
+                publishProviderState();
+                if (updateSessionInfosIfNeeded()) {
+                    notifySessionInfoUpdated();
+                }
+            });
+        });
 
-        // The methods below should be called after all fields are initialized, as they
+        // These methods below should be called after all fields are initialized, as they
         // access the fields inside.
-        updateDeviceRoute(newAudioRoutes);
+        updateProviderState();
         updateSessionInfosIfNeeded();
     }
 
@@ -216,7 +186,9 @@
             // The currently selected route is the default route.
             return;
         }
-        if (TextUtils.equals(routeId, mDeviceRoute.getId())) {
+
+        MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
+        if (TextUtils.equals(routeId, deviceRoute.getId())) {
             mBtRouteProvider.transferTo(null);
         } else {
             mBtRouteProvider.transferTo(routeId);
@@ -254,9 +226,12 @@
             if (mSessionInfos.isEmpty()) {
                 return null;
             }
+
+            MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
+
             RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder(
                     SYSTEM_SESSION_ID, packageName).setSystemSession(true);
-            builder.addSelectedRoute(mDeviceRoute.getId());
+            builder.addSelectedRoute(deviceRoute.getId());
             for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
                 builder.addTransferableRoute(route.getId());
             }
@@ -264,47 +239,12 @@
         }
     }
 
-    private void updateDeviceRoute(AudioRoutesInfo newRoutes) {
-        int name = R.string.default_audio_route_name;
-        int type = TYPE_BUILTIN_SPEAKER;
-        if (newRoutes != null) {
-            if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0) {
-                type = TYPE_WIRED_HEADPHONES;
-                name = com.android.internal.R.string.default_audio_route_name_headphones;
-            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) {
-                type = TYPE_WIRED_HEADSET;
-                name = com.android.internal.R.string.default_audio_route_name_headphones;
-            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) {
-                type = TYPE_DOCK;
-                name = com.android.internal.R.string.default_audio_route_name_dock_speakers;
-            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HDMI) != 0) {
-                type = TYPE_HDMI;
-                name = com.android.internal.R.string.default_audio_route_name_external_device;
-            } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_USB) != 0) {
-                type = TYPE_USB_DEVICE;
-                name = com.android.internal.R.string.default_audio_route_name_usb;
-            }
-        }
-
-        mDeviceRoute = new MediaRoute2Info.Builder(
-                DEVICE_ROUTE_ID, mContext.getResources().getText(name).toString())
-                .setVolumeHandling(mAudioManager.isVolumeFixed()
-                        ? MediaRoute2Info.PLAYBACK_VOLUME_FIXED
-                        : MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE)
-                .setVolume(mDeviceVolume)
-                .setVolumeMax(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC))
-                .setType(type)
-                .addFeature(FEATURE_LIVE_AUDIO)
-                .addFeature(FEATURE_LIVE_VIDEO)
-                .addFeature(FEATURE_LOCAL_PLAYBACK)
-                .setConnectionState(MediaRoute2Info.CONNECTION_STATE_CONNECTED)
-                .build();
-        updateProviderState();
-    }
-
     private void updateProviderState() {
         MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder();
-        builder.addRoute(mDeviceRoute);
+
+        // We must have a device route in the provider info.
+        builder.addRoute(mDeviceRouteController.getDeviceRoute());
+
         for (MediaRoute2Info route : mBtRouteProvider.getAllBluetoothRoutes()) {
             builder.addRoute(route);
         }
@@ -327,11 +267,12 @@
                     SYSTEM_SESSION_ID, "" /* clientPackageName */)
                     .setSystemSession(true);
 
-            MediaRoute2Info selectedRoute = mDeviceRoute;
+            MediaRoute2Info deviceRoute = mDeviceRouteController.getDeviceRoute();
+            MediaRoute2Info selectedRoute = deviceRoute;
             MediaRoute2Info selectedBtRoute = mBtRouteProvider.getSelectedRoute();
             if (selectedBtRoute != null) {
                 selectedRoute = selectedBtRoute;
-                builder.addTransferableRoute(mDeviceRoute.getId());
+                builder.addTransferableRoute(deviceRoute.getId());
             }
             mSelectedRouteId = selectedRoute.getId();
             mDefaultRoute = new MediaRoute2Info.Builder(DEFAULT_ROUTE_ID, selectedRoute)
@@ -423,12 +364,9 @@
         if (mBtRouteProvider.updateVolumeForDevices(devices, volume)) {
             return;
         }
-        if (mDeviceVolume != volume) {
-            mDeviceVolume = volume;
-            mDeviceRoute = new MediaRoute2Info.Builder(mDeviceRoute)
-                    .setVolume(volume)
-                    .build();
-        }
+
+        mDeviceRouteController.updateVolume(volume);
+
         publishProviderState();
     }
 
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 4b2c88c..2774462 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -20,7 +20,7 @@
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
-import static android.service.notification.DNDModeProto.ROOT_CONFIG;
+import static android.service.notification.NotificationServiceProto.ROOT_CONFIG;
 import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
 
 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index faa06f7..9bca9f0 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -404,7 +404,7 @@
                         "BackgroundDexOptService_" + (isPostBootUpdateJob ? "PostBoot" : "Idle"),
                         () -> {
                             TimingsTraceAndSlog tr =
-                                    new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_PACKAGE_MANAGER);
+                                    new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_DALVIK);
                             tr.traceBegin("jobExecution");
                             boolean completed = false;
                             boolean fatalError = false;
@@ -494,6 +494,8 @@
     @GuardedBy("mLock")
     private void waitForDexOptThreadToFinishLocked() {
         TimingsTraceAndSlog tr = new TimingsTraceAndSlog(TAG, Trace.TRACE_TAG_PACKAGE_MANAGER);
+        // This tracing section doesn't have any correspondence in ART Service - it never waits for
+        // cancellation to finish.
         tr.traceBegin("waitForDexOptThreadToFinishLocked");
         try {
             // Wait but check in regular internal to see if the thread is still alive.
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index fac7748..c232b36 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -678,8 +678,4 @@
 
     @NonNull
     Collection<SharedUserSetting> getAllSharedUsers();
-
-    boolean isChangeEnabled(long changeId, int uid);
-
-    boolean isChangeEnabled(long changeId, ApplicationInfo info);
 }
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 21f661b..5984360 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -125,7 +125,6 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Preconditions;
 import com.android.modules.utils.TypedXmlSerializer;
-import com.android.server.compat.PlatformCompat;
 import com.android.server.pm.Installer.LegacyDexoptDisabledException;
 import com.android.server.pm.dex.DexManager;
 import com.android.server.pm.dex.PackageDexUsage;
@@ -575,7 +574,8 @@
                     list = new ArrayList<>(1);
                     list.add(ri);
                     PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                            this, list, false, intent, resolvedType, filterCallingUid);
+                            mInjector.getCompatibility(), mComponentResolver,
+                            list, false, intent, resolvedType, filterCallingUid);
                 }
             }
         } else {
@@ -591,7 +591,7 @@
                     String callingPkgName = getInstantAppPackageName(filterCallingUid);
                     boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
                     lockedResult.result = maybeAddInstantAppInstaller(
-                            lockedResult.result, intent, resolvedType, flags, filterCallingUid,
+                            lockedResult.result, intent, resolvedType, flags,
                             userId, resolveForStart, isRequesterInstantApp);
                 }
                 if (lockedResult.sortResult) {
@@ -604,7 +604,8 @@
         if (originalIntent != null) {
             // We also have to ensure all components match the original intent
             PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                    this, list, false, originalIntent, resolvedType, filterCallingUid);
+                    mInjector.getCompatibility(), mComponentResolver,
+                    list, false, originalIntent, resolvedType, filterCallingUid);
         }
 
         return skipPostResolution ? list : applyPostResolutionFilter(
@@ -686,7 +687,8 @@
                     list = new ArrayList<>(1);
                     list.add(ri);
                     PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                            this, list, false, intent, resolvedType, callingUid);
+                            mInjector.getCompatibility(), mComponentResolver,
+                            list, false, intent, resolvedType, callingUid);
                 }
             }
         } else {
@@ -697,7 +699,8 @@
         if (originalIntent != null) {
             // We also have to ensure all components match the original intent
             PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                    this, list, false, originalIntent, resolvedType, callingUid);
+                    mInjector.getCompatibility(), mComponentResolver,
+                    list, false, originalIntent, resolvedType, callingUid);
         }
 
         return list;
@@ -710,7 +713,7 @@
         String pkgName = intent.getPackage();
         if (pkgName == null) {
             final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(this, intent,
-                    resolvedType, flags, callingUid, userId);
+                    resolvedType, flags, userId);
             if (resolveInfos == null) {
                 return Collections.emptyList();
             }
@@ -720,7 +723,7 @@
         final AndroidPackage pkg = mPackages.get(pkgName);
         if (pkg != null) {
             final List<ResolveInfo> resolveInfos = mComponentResolver.queryServices(this, intent,
-                    resolvedType, flags, pkg.getServices(), callingUid,
+                    resolvedType, flags, pkg.getServices(),
                     userId);
             if (resolveInfos == null) {
                 return Collections.emptyList();
@@ -750,7 +753,7 @@
                  {@link PackageManager.SKIP_CURRENT_PROFILE} set.
                  */
                 result.addAll(filterIfNotSystemUser(mComponentResolver.queryActivities(this,
-                        intent, resolvedType, flags, filterCallingUid, userId), userId));
+                        intent, resolvedType, flags, userId), userId));
             }
             addInstant = isInstantAppResolutionAllowed(intent, result, userId,
                     false /*skipPackageCheck*/, flags);
@@ -774,7 +777,7 @@
                     || !shouldFilterApplication(setting, filterCallingUid, userId))) {
                 result.addAll(filterIfNotSystemUser(mComponentResolver.queryActivities(this,
                         intent, resolvedType, flags, setting.getAndroidPackage().getActivities(),
-                        filterCallingUid, userId), userId));
+                        userId), userId));
             }
             if (result == null || result.size() == 0) {
                 // the caller wants to resolve for a particular package; however, there
@@ -1105,7 +1108,7 @@
             return null;
         }
         List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(this, intent,
-                resolvedType, flags, Binder.getCallingUid(), parentUserId);
+                resolvedType, flags, parentUserId);
 
         if (resultTargetUser == null || resultTargetUser.isEmpty()) {
             return null;
@@ -1343,7 +1346,7 @@
 
     private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result,
             Intent intent, String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags,
-            int callingUid, int userId, boolean resolveForStart, boolean isRequesterInstantApp) {
+            int userId, boolean resolveForStart, boolean isRequesterInstantApp) {
         // first, check to see if we've got an instant app already installed
         final boolean alreadyResolvedLocally = (flags & PackageManager.MATCH_INSTANT) != 0;
         ResolveInfo localInstantApp = null;
@@ -1356,7 +1359,6 @@
                             | PackageManager.GET_RESOLVED_FILTER
                             | PackageManager.MATCH_INSTANT
                             | PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY,
-                    callingUid,
                     userId);
             for (int i = instantApps.size() - 1; i >= 0; --i) {
                 final ResolveInfo info = instantApps.get(i);
@@ -3691,13 +3693,10 @@
                 ps, callingUid, component, TYPE_ACTIVITY, userId, true /* filterUninstall */)) {
             return false;
         }
-        final boolean callerBlocksNullAction = isChangeEnabled(
-                IntentFilter.BLOCK_NULL_ACTION_INTENTS, callingUid);
         for (int i=0; i< a.getIntents().size(); i++) {
             if (a.getIntents().get(i).getIntentFilter()
                     .match(intent.getAction(), resolvedType, intent.getScheme(),
-                            intent.getData(), intent.getCategories(), TAG,
-                            /*supportWildcards*/ false, callerBlocksNullAction, null, null) >= 0) {
+                            intent.getData(), intent.getCategories(), TAG) >= 0) {
                 return true;
             }
         }
@@ -5795,37 +5794,4 @@
     public UserInfo[] getUserInfos() {
         return mInjector.getUserManagerInternal().getUserInfos();
     }
-
-    @Override
-    public boolean isChangeEnabled(long changeId, int uid) {
-        final PlatformCompat compat = mInjector.getCompatibility();
-        int appId = UserHandle.getAppId(uid);
-        SettingBase s = mSettings.getSettingBase(appId);
-        if (s instanceof PackageSetting) {
-            var ps = (PackageSetting) s;
-            if (ps.getAndroidPackage() == null) return false;
-            var info = new ApplicationInfo();
-            info.packageName = ps.getPackageName();
-            info.targetSdkVersion = ps.getAndroidPackage().getTargetSdkVersion();
-            return compat.isChangeEnabledInternal(changeId, info);
-        } else if (s instanceof SharedUserSetting) {
-            var ss = (SharedUserSetting) s;
-            List<AndroidPackage> packages = ss.getPackages();
-            for (int i = 0; i < packages.size(); ++i) {
-                var pkg = packages.get(i);
-                var info = new ApplicationInfo();
-                info.packageName = pkg.getPackageName();
-                info.targetSdkVersion = pkg.getTargetSdkVersion();
-                if (compat.isChangeEnabledInternal(changeId, info)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public boolean isChangeEnabled(long changeId, ApplicationInfo info) {
-        return mInjector.getCompatibility().isChangeEnabledInternal(changeId, info);
-    }
 }
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java b/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java
index ee8f560..90d89c6 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileResolver.java
@@ -23,7 +23,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
-import android.os.Binder;
 import android.util.SparseBooleanArray;
 
 import com.android.internal.app.IntentForwarderActivity;
@@ -279,7 +278,7 @@
         }
 
         List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(computer, intent,
-                resolvedType, flags, Binder.getCallingUid(), targetUserId);
+                resolvedType, flags, targetUserId);
         if (CollectionUtils.isEmpty(resultTargetUser)) {
             return null;
         }
diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java
index 0fd81ac..a9d4115 100644
--- a/services/core/java/com/android/server/pm/DexOptHelper.java
+++ b/services/core/java/com/android/server/pm/DexOptHelper.java
@@ -16,7 +16,7 @@
 
 package com.android.server.pm;
 
-import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.os.Trace.TRACE_TAG_DALVIK;
 
 import static com.android.server.LocalManagerRegistry.ManagerNotFoundException;
 import static com.android.server.pm.ApexManager.ActiveApexInfo;
@@ -470,11 +470,11 @@
 
     @DexOptResult
     private int performDexOptTraced(DexoptOptions options) {
-        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+        Trace.traceBegin(TRACE_TAG_DALVIK, "dexopt");
         try {
             return performDexOptInternal(options);
         } finally {
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+            Trace.traceEnd(TRACE_TAG_DALVIK);
         }
     }
 
@@ -605,7 +605,7 @@
             throw new IllegalArgumentException("Can't dexopt APEX package: " + packageName);
         }
 
-        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
+        Trace.traceBegin(TRACE_TAG_DALVIK, "dexopt");
 
         // Whoever is calling forceDexOpt wants a compiled package.
         // Don't use profiles since that may cause compilation to be skipped.
@@ -615,7 +615,7 @@
 
         @DexOptResult int res = performDexOptInternalWithDependenciesLI(pkg, packageState, options);
 
-        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+        Trace.traceEnd(TRACE_TAG_DALVIK);
         if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) {
             throw new IllegalStateException("Failed to dexopt: " + res);
         }
diff --git a/services/core/java/com/android/server/pm/NoFilteringResolver.java b/services/core/java/com/android/server/pm/NoFilteringResolver.java
index e53e756..3923890 100644
--- a/services/core/java/com/android/server/pm/NoFilteringResolver.java
+++ b/services/core/java/com/android/server/pm/NoFilteringResolver.java
@@ -102,7 +102,7 @@
             boolean hasNonNegativePriorityResult,
             Function<String, PackageStateInternal> pkgSettingFunction) {
         List<ResolveInfo> resolveInfos = mComponentResolver.queryActivities(computer,
-                intent, resolvedType, flags, Binder.getCallingUid(), targetUserId);
+                intent, resolvedType, flags, targetUserId);
         List<CrossProfileDomainInfo> crossProfileDomainInfos = new ArrayList<>();
         if (resolveInfos != null) {
 
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index f338137..0a90e7a3 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -386,7 +386,7 @@
                             options.getCompilationReason());
                     // OTAPreopt doesn't have stats so don't report in that case.
                     if (packageStats != null) {
-                        Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "dex2oat-metrics");
+                        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "dex2oat-metrics");
                         try {
                             long sessionId = sRandom.nextLong();
                             ArtStatsLogUtils.writeStatsLog(
@@ -403,7 +403,7 @@
                                     dexCodeIsa,
                                     path);
                         } finally {
-                            Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER);
+                            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
                         }
                     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a42e78b..de5f0c4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6675,24 +6675,16 @@
         @Deprecated
         public void legacyDumpProfiles(String packageName, boolean dumpClassesAndMethods)
                 throws LegacyDexoptDisabledException {
-            /* Only the shell, root, or the app user should be able to dump profiles. */
-            final int callingUid = Binder.getCallingUid();
             final Computer snapshot = snapshotComputer();
-            final String[] callerPackageNames = snapshot.getPackagesForUid(callingUid);
-            if (!PackageManagerServiceUtils.isRootOrShell(callingUid)
-                    && !ArrayUtils.contains(callerPackageNames, packageName)) {
-                throw new SecurityException("dumpProfiles");
-            }
-
             AndroidPackage pkg = snapshot.getPackage(packageName);
             if (pkg == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
 
             synchronized (mInstallLock) {
-                Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dump profiles");
+                Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "dump profiles");
                 mArtManagerService.dumpProfiles(pkg, dumpClassesAndMethods);
-                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+                Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 9036d4c..928ffa7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -16,7 +16,6 @@
 
 package com.android.server.pm;
 
-import static android.content.IntentFilter.BLOCK_NULL_ACTION_INTENTS;
 import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
@@ -95,6 +94,7 @@
 import com.android.server.IntentResolver;
 import com.android.server.LocalManagerRegistry;
 import com.android.server.Watchdog;
+import com.android.server.compat.PlatformCompat;
 import com.android.server.pm.dex.PackageDexUsage;
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.pm.pkg.PackageStateInternal;
@@ -1166,8 +1166,10 @@
         return (ps.getFlags() & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
     }
 
+    // Static to give access to ComputeEngine
     public static void applyEnforceIntentFilterMatching(
-            Computer computer, List<ResolveInfo> resolveInfos, boolean isReceiver,
+            PlatformCompat compat, ComponentResolverApi resolver,
+            List<ResolveInfo> resolveInfos, boolean isReceiver,
             Intent intent, String resolvedType, int filterCallingUid) {
         if (DISABLE_ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS.get()) return;
 
@@ -1175,11 +1177,6 @@
                 ? new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM)
                 : null;
 
-        final boolean callerBlocksNullAction = computer.isChangeEnabled(
-                BLOCK_NULL_ACTION_INTENTS, filterCallingUid);
-
-        final ComponentResolverApi resolver = computer.getComponentResolver();
-
         for (int i = resolveInfos.size() - 1; i >= 0; --i) {
             final ComponentInfo info = resolveInfos.get(i).getComponentInfo();
 
@@ -1190,15 +1187,11 @@
             }
 
             // Only enforce filter matching if target app's target SDK >= T
-            if (!computer.isChangeEnabled(
+            if (!compat.isChangeEnabledInternal(
                     ENFORCE_INTENTS_TO_MATCH_INTENT_FILTERS, info.applicationInfo)) {
                 continue;
             }
 
-            // Block null action intent if either source or target app's target SDK >= U
-            final boolean blockNullAction = callerBlocksNullAction
-                    || computer.isChangeEnabled(BLOCK_NULL_ACTION_INTENTS, info.applicationInfo);
-
             final ParsedMainComponent comp;
             if (info instanceof ActivityInfo) {
                 if (isReceiver) {
@@ -1220,8 +1213,7 @@
             boolean match = false;
             for (int j = 0, size = comp.getIntents().size(); j < size; ++j) {
                 IntentFilter intentFilter = comp.getIntents().get(j).getIntentFilter();
-                if (IntentResolver.intentMatchesFilter(
-                        intentFilter, intent, resolvedType, blockNullAction)) {
+                if (IntentResolver.intentMatchesFilter(intentFilter, intent, resolvedType)) {
                     match = true;
                     break;
                 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 41592bd..586e112 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -391,6 +391,11 @@
     private int runLegacyDexoptCommand(@NonNull String cmd)
             throws RemoteException, LegacyDexoptDisabledException {
         Installer.checkLegacyDexoptDisabled();
+
+        if (!PackageManagerServiceUtils.isRootOrShell(Binder.getCallingUid())) {
+            throw new SecurityException("Dexopt shell commands need root or shell access");
+        }
+
         switch (cmd) {
             case "compile":
                 return runCompile();
diff --git a/services/core/java/com/android/server/pm/ResolveIntentHelper.java b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
index 8bca4a9..a13c568 100644
--- a/services/core/java/com/android/server/pm/ResolveIntentHelper.java
+++ b/services/core/java/com/android/server/pm/ResolveIntentHelper.java
@@ -466,14 +466,15 @@
                     list = new ArrayList<>(1);
                     list.add(ri);
                     PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                            computer, list, true, intent, resolvedType, filterCallingUid);
+                            mPlatformCompat, componentResolver, list, true, intent,
+                            resolvedType, filterCallingUid);
                 }
             }
         } else {
             String pkgName = intent.getPackage();
             if (pkgName == null) {
-                final List<ResolveInfo> result = componentResolver.queryReceivers(
-                        computer, intent, resolvedType, flags, filterCallingUid, userId);
+                final List<ResolveInfo> result = componentResolver
+                        .queryReceivers(computer, intent, resolvedType, flags, userId);
                 if (result != null) {
                     list = result;
                 }
@@ -481,7 +482,7 @@
             final AndroidPackage pkg = computer.getPackage(pkgName);
             if (pkg != null) {
                 final List<ResolveInfo> result = componentResolver.queryReceivers(computer,
-                        intent, resolvedType, flags, pkg.getReceivers(), filterCallingUid, userId);
+                        intent, resolvedType, flags, pkg.getReceivers(), userId);
                 if (result != null) {
                     list = result;
                 }
@@ -491,7 +492,8 @@
         if (originalIntent != null) {
             // We also have to ensure all components match the original intent
             PackageManagerServiceUtils.applyEnforceIntentFilterMatching(
-                    computer, list, true, originalIntent, resolvedType, filterCallingUid);
+                    mPlatformCompat, componentResolver,
+                    list, true, originalIntent, resolvedType, filterCallingUid);
         }
 
         return computer.applyPostResolutionFilter(list, instantAppPkgName, false, queryingUid,
@@ -575,7 +577,7 @@
         String pkgName = intent.getPackage();
         if (pkgName == null) {
             final List<ResolveInfo> resolveInfos = componentResolver.queryProviders(computer,
-                    intent, resolvedType, flags, callingUid, userId);
+                    intent, resolvedType, flags, userId);
             if (resolveInfos == null) {
                 return Collections.emptyList();
             }
@@ -585,7 +587,7 @@
         final AndroidPackage pkg = computer.getPackage(pkgName);
         if (pkg != null) {
             final List<ResolveInfo> resolveInfos = componentResolver.queryProviders(computer,
-                    intent, resolvedType, flags, pkg.getProviders(), callingUid, userId);
+                    intent, resolvedType, flags, pkg.getProviders(), userId);
             if (resolveInfos == null) {
                 return Collections.emptyList();
             }
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 6d5e2b0..67639fb 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -430,6 +430,7 @@
             @NonNull List<ShortcutInfo> changedShortcuts) {
         Preconditions.checkArgument(newShortcut.isEnabled(),
                 "pushDynamicShortcuts() cannot publish disabled shortcuts");
+        ensureShortcutCountBeforePush();
 
         newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
 
@@ -437,7 +438,7 @@
         final ShortcutInfo oldShortcut = findShortcutById(newShortcut.getId());
         boolean deleted = false;
 
-        if (oldShortcut == null) {
+        if (oldShortcut == null || !oldShortcut.isDynamic()) {
             final ShortcutService service = mShortcutUser.mService;
             final int maxShortcuts = service.getMaxActivityShortcuts();
 
@@ -446,18 +447,12 @@
             final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity());
 
             if (activityShortcuts != null && activityShortcuts.size() > maxShortcuts) {
-                Slog.e(TAG, "Error pushing shortcut. There are already "
-                        + activityShortcuts.size() + " shortcuts, exceeding the " + maxShortcuts
-                        + " shortcuts limit when pushing the new shortcut " + newShortcut
-                        + ". Id of shortcuts currently available in system memory are "
-                        + activityShortcuts.stream().map(ShortcutInfo::getId)
-                        .collect(Collectors.joining(",", "[", "]")));
-                // TODO: This should not have happened. If it does, identify the root cause where
-                //  possible, otherwise bail-out early to prevent memory issue.
+                // Root cause was discovered in b/233155034, so this should not be happening.
+                service.wtf("Error pushing shortcut. There are already "
+                        + activityShortcuts.size() + " shortcuts.");
             }
             if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) {
                 // Max has reached. Delete the shortcut with lowest rank.
-
                 // Sort by isManifestShortcut() and getRank().
                 Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator);
 
@@ -473,7 +468,8 @@
                 deleted = deleteDynamicWithId(shortcut.getId(), /* ignoreInvisible =*/ true,
                         /*ignorePersistedShortcuts=*/ true) != null;
             }
-        } else {
+        }
+        if (oldShortcut != null) {
             // It's an update case.
             // Make sure the target is updatable. (i.e. should be mutable.)
             oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
@@ -505,6 +501,32 @@
         return deleted;
     }
 
+    private void ensureShortcutCountBeforePush() {
+        final ShortcutService service = mShortcutUser.mService;
+        // Ensure the total number of shortcuts doesn't exceed the hard limit per app.
+        final int maxShortcutPerApp = service.getMaxAppShortcuts();
+        synchronized (mLock) {
+            final List<ShortcutInfo> appShortcuts = mShortcuts.values().stream().filter(si ->
+                    !si.isPinned()).collect(Collectors.toList());
+            if (appShortcuts.size() >= maxShortcutPerApp) {
+                // Max has reached. Removes shortcuts until they fall within the hard cap.
+                // Sort by isManifestShortcut(), isDynamic() and getLastChangedTimestamp().
+                Collections.sort(appShortcuts, mShortcutTypeRankAndTimeComparator);
+
+                while (appShortcuts.size() >= maxShortcutPerApp) {
+                    final ShortcutInfo shortcut = appShortcuts.remove(appShortcuts.size() - 1);
+                    if (shortcut.isDeclaredInManifest()) {
+                        // All shortcuts are manifest shortcuts and cannot be removed.
+                        throw new IllegalArgumentException(getPackageName() + " has published "
+                                + appShortcuts.size() + " manifest shortcuts across different"
+                                + " activities.");
+                    }
+                    forceDeleteShortcutInner(shortcut.getId());
+                }
+            }
+        }
+    }
+
     /**
      * Remove all shortcuts that aren't pinned, cached nor dynamic.
      *
@@ -1371,6 +1393,61 @@
     };
 
     /**
+     * To sort by isManifestShortcut(), isDynamic(), getRank() and
+     * getLastChangedTimestamp(). i.e. manifest shortcuts come before non-manifest shortcuts,
+     * dynamic shortcuts come before floating shortcuts, then sort by last changed timestamp.
+     *
+     * This is used to decide which shortcuts to remove when the total number of shortcuts retained
+     * for the app exceeds the limit defined in {@link ShortcutService#getMaxAppShortcuts()}.
+     *
+     * (Note the number of manifest shortcuts is always <= the max number, because if there are
+     * more, ShortcutParser would ignore the rest.)
+     */
+    final Comparator<ShortcutInfo> mShortcutTypeRankAndTimeComparator = (ShortcutInfo a,
+            ShortcutInfo b) -> {
+        if (a.isDeclaredInManifest() && !b.isDeclaredInManifest()) {
+            return -1;
+        }
+        if (!a.isDeclaredInManifest() && b.isDeclaredInManifest()) {
+            return 1;
+        }
+        if (a.isDynamic() && b.isDynamic()) {
+            return Integer.compare(a.getRank(), b.getRank());
+        }
+        if (a.isDynamic()) {
+            return -1;
+        }
+        if (b.isDynamic()) {
+            return 1;
+        }
+        if (a.isCached() && b.isCached()) {
+            // if both shortcuts are cached, prioritize shortcuts cached by people tile,
+            if (a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+                    && !b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+                return -1;
+            } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)
+                    && b.hasFlags(ShortcutInfo.FLAG_CACHED_PEOPLE_TILE)) {
+                return 1;
+            }
+            // followed by bubbles.
+            if (a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+                    && !b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+                return -1;
+            } else if (!a.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)
+                    && b.hasFlags(ShortcutInfo.FLAG_CACHED_BUBBLES)) {
+                return 1;
+            }
+        }
+        if (a.isCached()) {
+            return -1;
+        }
+        if (b.isCached()) {
+            return 1;
+        }
+        return Long.compare(b.getLastChangedTimestamp(), a.getLastChangedTimestamp());
+    };
+
+    /**
      * Build a list of shortcuts for each target activity and return as a map. The result won't
      * contain "floating" shortcuts because they don't belong on any activities.
      */
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index c6411ff..372b3bb 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -119,10 +119,9 @@
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.security.FileIntegrity;
 import com.android.server.uri.UriGrantsManagerInternal;
 
-import libcore.io.IoUtils;
-
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -181,6 +180,9 @@
     static final int DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY = 15;
 
     @VisibleForTesting
+    static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 100;
+
+    @VisibleForTesting
     static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96;
 
     @VisibleForTesting
@@ -207,6 +209,10 @@
     @VisibleForTesting
     static final String FILENAME_USER_PACKAGES = "shortcuts.xml";
 
+    @VisibleForTesting
+    static final String FILENAME_USER_PACKAGES_RESERVE_COPY =
+            FILENAME_USER_PACKAGES + ".reservecopy";
+
     static final String DIRECTORY_BITMAPS = "bitmaps";
 
     private static final String TAG_ROOT = "root";
@@ -257,6 +263,11 @@
         String KEY_MAX_SHORTCUTS = "max_shortcuts";
 
         /**
+         * Key name for the max shortcuts can be retained in system ram per app. (int)
+         */
+        String KEY_MAX_SHORTCUTS_PER_APP = "max_shortcuts_per_app";
+
+        /**
          * Key name for icon compression quality, 0-100.
          */
         String KEY_ICON_QUALITY = "icon_quality";
@@ -329,11 +340,16 @@
             new SparseArray<>();
 
     /**
-     * Max number of dynamic + manifest shortcuts that each application can have at a time.
+     * Max number of dynamic + manifest shortcuts that each activity can have at a time.
      */
     private int mMaxShortcuts;
 
     /**
+     * Max number of shortcuts that can exists in system ram for each application.
+     */
+    private int mMaxShortcutsPerApp;
+
+    /**
      * Max number of updating API calls that each application can make during the interval.
      */
     int mMaxUpdatesPerInterval;
@@ -807,6 +823,9 @@
         mMaxShortcuts = Math.max(0, (int) parser.getLong(
                 ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_ACTIVITY));
 
+        mMaxShortcutsPerApp = Math.max(0, (int) parser.getLong(
+                ConfigConstants.KEY_MAX_SHORTCUTS_PER_APP, DEFAULT_MAX_SHORTCUTS_PER_APP));
+
         final int iconDimensionDp = Math.max(1, injectIsLowRamDevice()
                 ? (int) parser.getLong(
                 ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM,
@@ -1055,6 +1074,11 @@
         return new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
     }
 
+    @VisibleForTesting
+    final File getReserveCopyUserFile(@UserIdInt int userId) {
+        return new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES_RESERVE_COPY);
+    }
+
     @GuardedBy("mLock")
     private void saveUserLocked(@UserIdInt int userId) {
         final File path = getUserFile(userId);
@@ -1062,6 +1086,9 @@
             Slog.d(TAG, "Saving to " + path);
         }
 
+        final File reservePath = getReserveCopyUserFile(userId);
+        reservePath.delete();
+
         path.getParentFile().mkdirs();
         final AtomicFile file = new AtomicFile(path);
         FileOutputStream os = null;
@@ -1079,6 +1106,23 @@
             file.failWrite(os);
         }
 
+        // Store the reserve copy of the file.
+        try (FileInputStream in = new FileInputStream(path);
+             FileOutputStream out = new FileOutputStream(reservePath)) {
+            FileUtils.copy(in, out);
+            FileUtils.sync(out);
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to write reserve copy: " + path, e);
+        }
+
+        // Protect both primary and reserve copy with fs-verity.
+        try {
+            FileIntegrity.setUpFsVerity(path);
+            FileIntegrity.setUpFsVerity(reservePath);
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to verity-protect", e);
+        }
+
         getUserShortcutsLocked(userId).logSharingShortcutStats(mMetricsLogger);
     }
 
@@ -1117,26 +1161,25 @@
         if (DEBUG || DEBUG_REBOOT) {
             Slog.d(TAG, "Loading from " + path);
         }
-        final AtomicFile file = new AtomicFile(path);
 
-        final FileInputStream in;
-        try {
-            in = file.openRead();
+        try (FileInputStream in = new AtomicFile(path).openRead()) {
+            return loadUserInternal(userId, in, /* forBackup= */ false);
         } catch (FileNotFoundException e) {
             if (DEBUG || DEBUG_REBOOT) {
                 Slog.d(TAG, "Not found " + path);
             }
-            return null;
+        } catch (Exception e) {
+            final File reservePath = getReserveCopyUserFile(userId);
+            Slog.e(TAG, "Reading from reserve copy: " + reservePath, e);
+            try (FileInputStream in = new AtomicFile(reservePath).openRead()) {
+                return loadUserInternal(userId, in, /* forBackup= */ false);
+            } catch (Exception exceptionReadingReserveFile) {
+                Slog.e(TAG, "Failed to read reserve copy: " + reservePath,
+                        exceptionReadingReserveFile);
+            }
+            Slog.e(TAG, "Failed to read file " + path, e);
         }
-        try {
-            final ShortcutUser ret = loadUserInternal(userId, in, /* forBackup= */ false);
-            return ret;
-        } catch (IOException | XmlPullParserException | InvalidFileFormatException e) {
-            Slog.e(TAG, "Failed to read file " + file.getBaseFile(), e);
-            return null;
-        } finally {
-            IoUtils.closeQuietly(in);
-        }
+        return null;
     }
 
     private ShortcutUser loadUserInternal(@UserIdInt int userId, InputStream is,
@@ -1759,6 +1802,13 @@
     }
 
     /**
+     * Return the max number of shortcuts can be retaiend in system ram for each application.
+     */
+    int getMaxAppShortcuts() {
+        return mMaxShortcutsPerApp;
+    }
+
+    /**
      * - Sends a notification to LauncherApps
      * - Write to file
      */
@@ -4323,14 +4373,8 @@
             @NonNull ComponentName activity, @UserIdInt int userId) {
         final long start = getStatStartTime();
         try {
-            final ActivityInfo ai;
-            try {
-                ai = mContext.getPackageManager().getActivityInfoAsUser(activity,
-                        PackageManager.ComponentInfoFlags.of(PACKAGE_MATCH_FLAGS), userId);
-            } catch (NameNotFoundException e) {
-                return false;
-            }
-            return ai.enabled && ai.exported;
+            return queryActivities(new Intent(), activity.getPackageName(), activity, userId)
+                    .size() > 0;
         } finally {
             logDurationStat(Stats.IS_ACTIVITY_ENABLED, start);
         }
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index 07d36b3..18eebe4 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -27,6 +27,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
+import android.app.AppOpsManager;
 import android.app.IActivityManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.Intent;
@@ -39,6 +40,7 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.DeviceConfig;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.IntArray;
@@ -63,6 +65,9 @@
 import java.util.function.Predicate;
 
 public final class SuspendPackageHelper {
+
+    private static final String SYSTEM_EXEMPT_FROM_SUSPENSION = "system_exempt_from_suspension";
+
     // TODO(b/198166813): remove PMS dependency
     private final PackageManagerService mPm;
     private final PackageManagerServiceInjector mInjector;
@@ -502,6 +507,10 @@
             final String requiredPermissionControllerPackage =
                     getKnownPackageName(snapshot, KnownPackages.PACKAGE_PERMISSION_CONTROLLER,
                             userId);
+            final AppOpsManager appOpsManager = mInjector.getSystemService(AppOpsManager.class);
+            final boolean isSystemExemptFlagEnabled = DeviceConfig.getBoolean(
+                    DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
+                    SYSTEM_EXEMPT_FROM_SUSPENSION, /* defaultValue= */ true);
             for (int i = 0; i < packageNames.length; i++) {
                 canSuspend[i] = false;
                 final String packageName = packageNames[i];
@@ -558,6 +567,7 @@
                 PackageStateInternal packageState = snapshot.getPackageStateInternal(packageName);
                 AndroidPackage pkg = packageState == null ? null : packageState.getPkg();
                 if (pkg != null) {
+                    final int uid = UserHandle.getUid(userId, packageState.getAppId());
                     // Cannot suspend SDK libs as they are controlled by SDK manager.
                     if (pkg.isSdkLibrary()) {
                         Slog.w(TAG, "Cannot suspend package: " + packageName
@@ -574,6 +584,13 @@
                                 + pkg.getStaticSharedLibraryName());
                         continue;
                     }
+                    if (isSystemExemptFlagEnabled && appOpsManager.checkOpNoThrow(
+                            AppOpsManager.OP_SYSTEM_EXEMPT_FROM_SUSPENSION, uid, packageName)
+                            == AppOpsManager.MODE_ALLOWED) {
+                        Slog.w(TAG, "Cannot suspend package \"" + packageName
+                                + "\": has OP_SYSTEM_EXEMPT_FROM_SUSPENSION set");
+                        continue;
+                    }
                 }
                 if (PLATFORM_PACKAGE_NAME.equals(packageName)) {
                     Slog.w(TAG, "Cannot suspend the platform package: " + packageName);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index dd014ee..2b08a2c 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -114,6 +114,7 @@
 import android.util.TypedValue;
 import android.util.Xml;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IAppOpsService;
@@ -7369,9 +7370,19 @@
      * If the main user is a permanent admin user it can't be deleted
      * or downgraded to non-admin status.
      */
-    private static boolean isMainUserPermanentAdmin() {
+    public boolean isMainUserPermanentAdmin() {
         return Resources.getSystem()
-                .getBoolean(com.android.internal.R.bool.config_isMainUserPermanentAdmin);
+                .getBoolean(R.bool.config_isMainUserPermanentAdmin);
+    }
+
+    /**
+     * Returns true if {@link com.android.internal.R.bool#config_canSwitchToHeadlessSystemUser}
+     * is true. If allowed, headless system user can run in the foreground even though
+     * it is not a full user.
+     */
+    public boolean canSwitchToHeadlessSystemUser() {
+        return Resources.getSystem()
+                .getBoolean(R.bool.config_canSwitchToHeadlessSystemUser);
     }
 
 }
diff --git a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
index eed2a78..98b24ea 100644
--- a/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
+++ b/services/core/java/com/android/server/pm/UserManagerServiceShellCommand.java
@@ -150,6 +150,10 @@
                     return runIsUserVisible();
                 case "get-main-user":
                     return runGetMainUserId();
+                case "can-switch-to-headless-system-user":
+                    return canSwitchToHeadlessSystemUser();
+                case "is-main-user-permanent-admin":
+                    return isMainUserPermanentAdmin();
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -532,6 +536,20 @@
         return 0;
     }
 
+    private int canSwitchToHeadlessSystemUser() {
+        PrintWriter pw = getOutPrintWriter();
+        boolean canSwitchToHeadlessSystemUser = mService.canSwitchToHeadlessSystemUser();
+        pw.println(canSwitchToHeadlessSystemUser);
+        return 0;
+    }
+
+    private int isMainUserPermanentAdmin() {
+        PrintWriter pw = getOutPrintWriter();
+        boolean isMainUserPermanentAdmin = mService.isMainUserPermanentAdmin();
+        pw.println(isMainUserPermanentAdmin);
+        return 0;
+    }
+
     /**
      * Gets the {@link UserManager} associated with the context of the given user.
      */
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 977fab1..fac681a 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -807,10 +807,10 @@
         }
     }
 
-    private abstract static class MimeGroupsAwareIntentResolver<F extends ParsedComponent>
-            extends IntentResolver<Pair<F, ParsedIntentInfo>, ResolveInfo> {
-        private final ArrayMap<String, Pair<F, ParsedIntentInfo>[]> mMimeGroupToFilter =
-                new ArrayMap<>();
+    private abstract static class MimeGroupsAwareIntentResolver<F extends Pair<?
+            extends ParsedComponent, ParsedIntentInfo>, R>
+            extends IntentResolver<F, R> {
+        private final ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
         private boolean mIsUpdatingMimeGroup = false;
 
         @NonNull
@@ -822,7 +822,7 @@
         }
 
         // Copy constructor used in creating snapshots
-        MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F> orig,
+        MimeGroupsAwareIntentResolver(MimeGroupsAwareIntentResolver<F, R> orig,
                 @NonNull UserManagerService userManager) {
             mUserManager = userManager;
             copyFrom(orig);
@@ -831,7 +831,7 @@
         }
 
         @Override
-        public void addFilter(@Nullable PackageDataSnapshot snapshot, Pair<F, ParsedIntentInfo> f) {
+        public void addFilter(@Nullable PackageDataSnapshot snapshot, F f) {
             IntentFilter intentFilter = getIntentFilter(f);
             // We assume Computer is available for this class and all subclasses. Because this class
             // uses subclass method override to handle logic, the Computer parameter must be in the
@@ -846,7 +846,7 @@
         }
 
         @Override
-        protected void removeFilterInternal(Pair<F, ParsedIntentInfo> f) {
+        protected void removeFilterInternal(F f) {
             IntentFilter intentFilter = getIntentFilter(f);
             if (!mIsUpdatingMimeGroup) {
                 unregister_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
@@ -857,86 +857,6 @@
             intentFilter.clearDynamicDataTypes();
         }
 
-        @Override
-        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
-                String resolvedType, boolean defaultOnly, int callingUid, @UserIdInt int userId) {
-            if (!mUserManager.exists(userId)) return null;
-            long flags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
-            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, callingUid,
-                    userId, flags);
-        }
-
-        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
-                String resolvedType, long flags, int callingUid, int userId) {
-            if (!mUserManager.exists(userId)) return null;
-            return super.queryIntent(computer, intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, callingUid, userId, flags);
-        }
-
-        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
-                String resolvedType, long flags, List<F> packageComponents,
-                int callingUid, int userId) {
-            if (!mUserManager.exists(userId)) {
-                return null;
-            }
-            if (packageComponents == null) {
-                return Collections.emptyList();
-            }
-            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final int componentsSize = packageComponents.size();
-            ArrayList<Pair<F, ParsedIntentInfo>[]> listCut = new ArrayList<>(componentsSize);
-
-            List<ParsedIntentInfo> intentFilters;
-            for (int i = 0; i < componentsSize; ++i) {
-                F component = packageComponents.get(i);
-                intentFilters = component.getIntents();
-                if (!intentFilters.isEmpty()) {
-                    Pair<F, ParsedIntentInfo>[] array = newArray(intentFilters.size());
-                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
-                        array[arrayIndex] = Pair.create(component, intentFilters.get(arrayIndex));
-                    }
-                    listCut.add(array);
-                }
-            }
-            return super.queryIntentFromList(computer, intent, resolvedType,
-                    defaultOnly, listCut, callingUid, userId, flags);
-        }
-
-        @Override
-        protected boolean isPackageForFilter(String packageName, Pair<F, ParsedIntentInfo> info) {
-            return packageName.equals(info.first.getPackageName());
-        }
-
-        @Override
-        protected void sortResults(List<ResolveInfo> results) {
-            results.sort(RESOLVE_PRIORITY_SORTER);
-        }
-
-        @Override
-        protected void filterResults(@NonNull Computer computer, @NonNull Intent intent,
-                List<ResolveInfo> results) {
-            if (intent.getAction() != null) return;
-            // When the resolved component is targeting U+, block null action intents
-            for (int i = results.size() - 1; i >= 0; --i) {
-                if (computer.isChangeEnabled(IntentFilter.BLOCK_NULL_ACTION_INTENTS,
-                        results.get(i).getComponentInfo().applicationInfo)) {
-                    results.remove(i);
-                }
-            }
-        }
-
-        @Override
-        protected Pair<F, ParsedIntentInfo>[] newArray(int size) {
-            //noinspection unchecked
-            return (Pair<F, ParsedIntentInfo>[]) new Pair<?, ?>[size];
-        }
-
-        @Override
-        protected IntentFilter getIntentFilter(
-                @NonNull Pair<F, ParsedIntentInfo> input) {
-            return input.second.getIntentFilter();
-        }
-
         /**
          * Updates MIME group by applying changes to all IntentFilters
          * that contain the group and repopulating m*ToFilter maps accordingly
@@ -947,12 +867,12 @@
          */
         public boolean updateMimeGroup(@NonNull Computer computer, String packageName,
                 String mimeGroup) {
-            Pair<F, ParsedIntentInfo>[] filters = mMimeGroupToFilter.get(mimeGroup);
+            F[] filters = mMimeGroupToFilter.get(mimeGroup);
             int n = filters != null ? filters.length : 0;
 
             mIsUpdatingMimeGroup = true;
             boolean hasChanges = false;
-            Pair<F, ParsedIntentInfo> filter;
+            F filter;
             for (int i = 0; i < n && (filter = filters[i]) != null; i++) {
                 if (isPackageForFilter(packageName, filter)) {
                     hasChanges |= updateFilter(computer, filter);
@@ -962,7 +882,7 @@
             return hasChanges;
         }
 
-        private boolean updateFilter(@NonNull Computer computer, Pair<F, ParsedIntentInfo> f) {
+        private boolean updateFilter(@NonNull Computer computer, F f) {
             IntentFilter filter = getIntentFilter(f);
             List<String> oldTypes = filter.dataTypes();
             removeFilter(f);
@@ -987,7 +907,7 @@
             return first.equals(second);
         }
 
-        private void applyMimeGroups(@NonNull Computer computer, Pair<F, ParsedIntentInfo> f) {
+        private void applyMimeGroups(@NonNull Computer computer, F f) {
             IntentFilter filter = getIntentFilter(f);
 
             for (int i = filter.countMimeGroups() - 1; i >= 0; i--) {
@@ -1011,8 +931,8 @@
         }
 
         @Override
-        protected boolean isFilterStopped(@NonNull Computer computer,
-                Pair<F, ParsedIntentInfo> filter, @UserIdInt int userId) {
+        protected boolean isFilterStopped(@NonNull Computer computer, F filter,
+                @UserIdInt int userId) {
             if (!mUserManager.exists(userId)) {
                 return true;
             }
@@ -1028,7 +948,7 @@
     }
 
     public static class ActivityIntentResolver
-            extends MimeGroupsAwareIntentResolver<ParsedActivity> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {
 
         @NonNull
         private UserNeedsBadgingCache mUserNeedsBadging;
@@ -1049,6 +969,53 @@
             mUserNeedsBadging = userNeedsBadgingCache;
         }
 
+        @Override
+        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+                String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+            if (!mUserManager.exists(userId)) return null;
+            long flags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
+            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
+        }
+
+        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            return super.queryIntent(computer, intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
+        }
+
+        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, List<ParsedActivity> packageActivities,
+                int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            if (packageActivities == null) {
+                return Collections.emptyList();
+            }
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int activitiesSize = packageActivities.size();
+            ArrayList<Pair<ParsedActivity, ParsedIntentInfo>[]> listCut =
+                    new ArrayList<>(activitiesSize);
+
+            List<ParsedIntentInfo> intentFilters;
+            for (int i = 0; i < activitiesSize; ++i) {
+                ParsedActivity activity = packageActivities.get(i);
+                intentFilters = activity.getIntents();
+                if (!intentFilters.isEmpty()) {
+                    Pair<ParsedActivity, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+                        array[arrayIndex] = Pair.create(activity, intentFilters.get(arrayIndex));
+                    }
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(computer, intent, resolvedType,
+                    defaultOnly, listCut, userId, flags);
+        }
+
         protected void addActivity(@NonNull Computer computer, ParsedActivity a, String type,
                 List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) {
             mActivities.put(a.getComponentName(), a);
@@ -1105,6 +1072,18 @@
             return true;
         }
 
+        @Override
+        protected Pair<ParsedActivity, ParsedIntentInfo>[] newArray(int size) {
+            //noinspection unchecked
+            return (Pair<ParsedActivity, ParsedIntentInfo>[]) new Pair<?, ?>[size];
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                Pair<ParsedActivity, ParsedIntentInfo> info) {
+            return packageName.equals(info.first.getPackageName());
+        }
+
         private void log(String reason, ParsedIntentInfo info, int match,
                 int userId) {
             Slog.w(TAG, reason
@@ -1220,6 +1199,11 @@
         }
 
         @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
         protected void dumpFilter(PrintWriter out, String prefix,
                 Pair<ParsedActivity, ParsedIntentInfo> pair) {
             ParsedActivity activity = pair.first;
@@ -1253,6 +1237,12 @@
             out.println();
         }
 
+        @Override
+        protected IntentFilter getIntentFilter(
+                @NonNull Pair<ParsedActivity, ParsedIntentInfo> input) {
+            return input.second.getIntentFilter();
+        }
+
         protected List<ParsedActivity> getResolveList(AndroidPackage pkg) {
             return pkg.getActivities();
         }
@@ -1288,7 +1278,7 @@
     }
 
     public static final class ProviderIntentResolver
-            extends MimeGroupsAwareIntentResolver<ParsedProvider> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> {
         // Default constructor
         ProviderIntentResolver(@NonNull UserManagerService userManager) {
             super(userManager);
@@ -1301,6 +1291,57 @@
             mProviders.putAll(orig.mProviders);
         }
 
+        @Override
+        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+                String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            long flags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
+        }
+
+        @Nullable
+        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            return super.queryIntent(computer, intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
+        }
+
+        @Nullable
+        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, List<ParsedProvider> packageProviders,
+                int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            if (packageProviders == null) {
+                return Collections.emptyList();
+            }
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int providersSize = packageProviders.size();
+            ArrayList<Pair<ParsedProvider, ParsedIntentInfo>[]> listCut =
+                    new ArrayList<>(providersSize);
+
+            List<ParsedIntentInfo> intentFilters;
+            for (int i = 0; i < providersSize; ++i) {
+                ParsedProvider provider = packageProviders.get(i);
+                intentFilters = provider.getIntents();
+                if (!intentFilters.isEmpty()) {
+                    Pair<ParsedProvider, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+                        array[arrayIndex] = Pair.create(provider, intentFilters.get(arrayIndex));
+                    }
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(computer, intent, resolvedType,
+                    defaultOnly, listCut, userId, flags);
+        }
+
         void addProvider(@NonNull Computer computer, ParsedProvider p) {
             if (mProviders.containsKey(p.getComponentName())) {
                 Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
@@ -1361,6 +1402,18 @@
         }
 
         @Override
+        protected Pair<ParsedProvider, ParsedIntentInfo>[] newArray(int size) {
+            //noinspection unchecked
+            return (Pair<ParsedProvider, ParsedIntentInfo>[]) new Pair<?, ?>[size];
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                Pair<ParsedProvider, ParsedIntentInfo> info) {
+            return packageName.equals(info.first.getPackageName());
+        }
+
+        @Override
         protected ResolveInfo newResult(@NonNull Computer computer,
                 Pair<ParsedProvider, ParsedIntentInfo> pair, int match, int userId,
                 long customFlags) {
@@ -1426,6 +1479,11 @@
         }
 
         @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
         protected void dumpFilter(PrintWriter out, String prefix,
                 Pair<ParsedProvider, ParsedIntentInfo> pair) {
             ParsedProvider provider = pair.first;
@@ -1460,11 +1518,17 @@
             out.println();
         }
 
+        @Override
+        protected IntentFilter getIntentFilter(
+                @NonNull Pair<ParsedProvider, ParsedIntentInfo> input) {
+            return input.second.getIntentFilter();
+        }
+
         final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>();
     }
 
     public static final class ServiceIntentResolver
-            extends MimeGroupsAwareIntentResolver<ParsedService> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> {
         // Default constructor
         ServiceIntentResolver(@NonNull UserManagerService userManager) {
             super(userManager);
@@ -1477,6 +1541,50 @@
             mServices.putAll(orig.mServices);
         }
 
+        @Override
+        public List<ResolveInfo> queryIntent(@NonNull PackageDataSnapshot snapshot, Intent intent,
+                String resolvedType, boolean defaultOnly, @UserIdInt int userId) {
+            if (!mUserManager.exists(userId)) {
+                return null;
+            }
+            long flags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+            return super.queryIntent(snapshot, intent, resolvedType, defaultOnly, userId, flags);
+        }
+
+        List<ResolveInfo> queryIntent(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, int userId) {
+            if (!mUserManager.exists(userId)) return null;
+            return super.queryIntent(computer, intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId, flags);
+        }
+
+        List<ResolveInfo> queryIntentForPackage(@NonNull Computer computer, Intent intent,
+                String resolvedType, long flags, List<ParsedService> packageServices, int userId) {
+            if (!mUserManager.exists(userId)) return null;
+            if (packageServices == null) {
+                return Collections.emptyList();
+            }
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int servicesSize = packageServices.size();
+            ArrayList<Pair<ParsedService, ParsedIntentInfo>[]> listCut =
+                    new ArrayList<>(servicesSize);
+
+            List<ParsedIntentInfo> intentFilters;
+            for (int i = 0; i < servicesSize; ++i) {
+                ParsedService service = packageServices.get(i);
+                intentFilters = service.getIntents();
+                if (intentFilters.size() > 0) {
+                    Pair<ParsedService, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+                        array[arrayIndex] = Pair.create(service, intentFilters.get(arrayIndex));
+                    }
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(computer, intent, resolvedType,
+                    defaultOnly, listCut, userId, flags);
+        }
+
         void addService(@NonNull Computer computer, ParsedService s) {
             mServices.put(s.getComponentName(), s);
             if (DEBUG_SHOW_INFO) {
@@ -1532,6 +1640,18 @@
         }
 
         @Override
+        protected Pair<ParsedService, ParsedIntentInfo>[] newArray(int size) {
+            //noinspection unchecked
+            return (Pair<ParsedService, ParsedIntentInfo>[]) new Pair<?, ?>[size];
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                Pair<ParsedService, ParsedIntentInfo> info) {
+            return packageName.equals(info.first.getPackageName());
+        }
+
+        @Override
         protected ResolveInfo newResult(@NonNull Computer computer,
                 Pair<ParsedService, ParsedIntentInfo> pair, int match, int userId,
                 long customFlags) {
@@ -1590,6 +1710,11 @@
         }
 
         @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
         protected void dumpFilter(PrintWriter out, String prefix,
                 Pair<ParsedService, ParsedIntentInfo> pair) {
             ParsedService service = pair.first;
@@ -1627,6 +1752,12 @@
             out.println();
         }
 
+        @Override
+        protected IntentFilter getIntentFilter(
+                @NonNull Pair<ParsedService, ParsedIntentInfo> input) {
+            return input.second.getIntentFilter();
+        }
+
         // Keys are String (activity class name), values are Activity.
         final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>();
     }
@@ -1690,8 +1821,7 @@
         }
 
         @Override
-        protected void filterResults(@NonNull Computer computer,
-                @NonNull Intent intent, List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
+        protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
             // only do work if ordering is enabled [most of the time it won't be]
             if (mOrderResult.size() == 0) {
                 return;
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
index 7f88660..b8e4c8d 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
@@ -55,12 +55,12 @@
 
     @Nullable
     List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
 
     @Nullable
     List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
-            int callingUid, @UserIdInt int userId);
+            @UserIdInt int userId);
 
     @Nullable
     ProviderInfo queryProvider(@NonNull Computer computer, @NonNull String authority, long flags,
@@ -68,12 +68,12 @@
 
     @Nullable
     List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
 
     @Nullable
     List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
-            int callingUid, @UserIdInt int userId);
+            @UserIdInt int userId);
 
     @Nullable
     List<ProviderInfo> queryProviders(@NonNull Computer computer, @Nullable String processName,
@@ -81,21 +81,21 @@
 
     @Nullable
     List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
 
     @Nullable
     List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
-            int callingUid, @UserIdInt int userId);
+            @UserIdInt int userId);
 
     @Nullable
     List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId);
+            @Nullable String resolvedType, long flags, @UserIdInt int userId);
 
     @Nullable
     List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
-            int callingUid, @UserIdInt int userId);
+            @UserIdInt int userId);
 
     void querySyncProviders(@NonNull Computer computer, @NonNull List<String> outNames,
             @NonNull List<ProviderInfo> outInfo, boolean safeMode, @UserIdInt int userId);
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
index 6899924..9115775 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
@@ -126,17 +126,17 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, int userId) {
-        return mActivities.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+            @Nullable String resolvedType, long flags, int userId) {
+        return mActivities.queryIntent(computer, intent, resolvedType, flags, userId);
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
-            int callingUid, int userId) {
+            int userId) {
         return mActivities.queryIntentForPackage(computer, intent, resolvedType, flags, activities,
-                callingUid, userId);
+                userId);
     }
 
     @Nullable
@@ -168,17 +168,17 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, int userId) {
-        return mProviders.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+            @Nullable String resolvedType, long flags, int userId) {
+        return mProviders.queryIntent(computer, intent, resolvedType, flags, userId);
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         return mProviders.queryIntentForPackage(computer, intent, resolvedType, flags, providers,
-                callingUid, userId);
+                userId);
     }
 
     @Nullable
@@ -241,33 +241,33 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, int userId) {
-        return mReceivers.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+            @Nullable String resolvedType, long flags, int userId) {
+        return mReceivers.queryIntent(computer, intent, resolvedType, flags, userId);
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         return mReceivers.queryIntentForPackage(computer, intent, resolvedType, flags, receivers,
-                callingUid, userId);
+                userId);
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
-        return mServices.queryIntent(computer, intent, resolvedType, flags, callingUid, userId);
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
+        return mServices.queryIntent(computer, intent, resolvedType, flags, userId);
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         return mServices.queryIntentForPackage(computer, intent, resolvedType, flags, services,
-                callingUid, userId);
+                userId);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
index 5bfb135..0c84f4c 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
@@ -92,9 +92,9 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryActivities(computer, intent, resolvedType, flags, callingUid, userId);
+            return super.queryActivities(computer, intent, resolvedType, flags, userId);
         }
     }
 
@@ -102,10 +102,9 @@
     @Override
     public List<ResolveInfo> queryActivities(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> activities,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryActivities(computer, intent, resolvedType, flags, activities,
-                    callingUid, userId);
+            return super.queryActivities(computer, intent, resolvedType, flags, activities, userId);
         }
     }
 
@@ -121,9 +120,9 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryProviders(computer, intent, resolvedType, flags, callingUid, userId);
+            return super.queryProviders(computer, intent, resolvedType, flags, userId);
         }
     }
 
@@ -131,10 +130,9 @@
     @Override
     public List<ResolveInfo> queryProviders(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedProvider> providers,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryProviders(computer, intent, resolvedType, flags, providers,
-                    callingUid, userId);
+            return super.queryProviders(computer, intent, resolvedType, flags, providers, userId);
         }
     }
 
@@ -151,9 +149,9 @@
     @Nullable
     @Override
     public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryReceivers(computer, intent, resolvedType, flags, callingUid, userId);
+            return super.queryReceivers(computer, intent, resolvedType, flags, userId);
         }
     }
 
@@ -161,19 +159,18 @@
     @Override
     public List<ResolveInfo> queryReceivers(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedActivity> receivers,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryReceivers(computer, intent, resolvedType, flags, receivers,
-                    callingUid, userId);
+            return super.queryReceivers(computer, intent, resolvedType, flags, receivers, userId);
         }
     }
 
     @Nullable
     @Override
     public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
-            @Nullable String resolvedType, long flags, int callingUid, @UserIdInt int userId) {
+            @Nullable String resolvedType, long flags, @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryServices(computer, intent, resolvedType, flags, callingUid, userId);
+            return super.queryServices(computer, intent, resolvedType, flags, userId);
         }
     }
 
@@ -181,10 +178,9 @@
     @Override
     public List<ResolveInfo> queryServices(@NonNull Computer computer, @NonNull Intent intent,
             @Nullable String resolvedType, long flags, @NonNull List<ParsedService> services,
-            int callingUid, @UserIdInt int userId) {
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            return super.queryServices(computer, intent, resolvedType, flags, services, callingUid,
-                    userId);
+            return super.queryServices(computer, intent, resolvedType, flags, services, userId);
         }
     }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index a24f129..45dc49d 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -89,6 +89,7 @@
 
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManager.RecentTaskInfo;
@@ -160,6 +161,7 @@
 import android.service.vr.IPersistentVrStateCallbacks;
 import android.speech.RecognizerIntent;
 import android.telecom.TelecomManager;
+import android.util.FeatureFlagUtils;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.MutableBoolean;
@@ -330,6 +332,10 @@
     static final int TRIPLE_PRESS_PRIMARY_NOTHING = 0;
     static final int TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY = 1;
 
+    // Must match: config_searchKeyBehavior in config.xml
+    static final int SEARCH_BEHAVIOR_DEFAULT_SEARCH = 0;
+    static final int SEARCH_BEHAVIOR_TARGET_ACTIVITY = 1;
+
     static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -398,7 +404,6 @@
     ActivityTaskManagerInternal mActivityTaskManagerInternal;
     AutofillManagerInternal mAutofillManagerInternal;
     InputManagerInternal mInputManagerInternal;
-    InputMethodManagerInternal mInputMethodManagerInternal;
     DreamManagerInternal mDreamManagerInternal;
     PowerManagerInternal mPowerManagerInternal;
     IStatusBarService mStatusBarService;
@@ -539,6 +544,8 @@
     boolean mWakeOnAssistKeyPress;
     boolean mWakeOnBackKeyPress;
     long mWakeUpToLastStateTimeout;
+    int mSearchKeyBehavior;
+    ComponentName mSearchKeyTargetActivity;
 
     private boolean mHandleVolumeKeysInWM;
 
@@ -659,6 +666,7 @@
     private static final int MSG_HANDLE_ALL_APPS = 22;
     private static final int MSG_LAUNCH_ASSIST = 23;
     private static final int MSG_RINGER_TOGGLE_CHORD = 24;
+    private static final int MSG_SWITCH_KEYBOARD_LAYOUT = 25;
 
     private class PolicyHandler extends Handler {
         @Override
@@ -729,6 +737,9 @@
                 case MSG_SCREENSHOT_CHORD:
                     handleScreenShot(msg.arg1);
                     break;
+                case MSG_SWITCH_KEYBOARD_LAYOUT:
+                    handleSwitchKeyboardLayout(msg.arg1, msg.arg2);
+                    break;
             }
         }
     }
@@ -1025,14 +1036,8 @@
                     break;
                 case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
                     if (mDismissImeOnBackKeyPressed) {
-                        if (mInputMethodManagerInternal == null) {
-                            mInputMethodManagerInternal =
-                                    LocalServices.getService(InputMethodManagerInternal.class);
-                        }
-                        if (mInputMethodManagerInternal != null) {
-                            mInputMethodManagerInternal.hideCurrentInputMethod(
+                        InputMethodManagerInternal.get().hideCurrentInputMethod(
                                     SoftInputShowHideReason.HIDE_POWER_BUTTON_GO_HOME);
-                        }
                     } else {
                         shortPressPowerGoHome();
                     }
@@ -2140,6 +2145,12 @@
         mWakeUpToLastStateTimeout = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_wakeUpToLastStateTimeoutMillis);
 
+        mSearchKeyBehavior = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_searchKeyBehavior);
+
+        mSearchKeyTargetActivity = ComponentName.unflattenFromString(
+            mContext.getResources().getString(
+                com.android.internal.R.string.config_searchKeyTargetActivity));
         readConfigurationDependentBehaviors();
 
         mDisplayFoldController = DisplayFoldController.create(mContext, DEFAULT_DISPLAY);
@@ -2978,15 +2989,8 @@
                 break;
             case KeyEvent.KEYCODE_N:
                 if (down && event.isMetaPressed()) {
-                    IStatusBarService service = getStatusBarService();
-                    if (service != null) {
-                        try {
-                            service.expandNotificationsPanel();
-                        } catch (RemoteException e) {
-                            // do nothing.
-                        }
-                        return key_consumed;
-                    }
+                    toggleNotificationPanel();
+                    return key_consumed;
                 }
                 break;
             case KeyEvent.KEYCODE_S:
@@ -3169,7 +3173,19 @@
                     toggleNotificationPanel();
                 }
                 return key_consumed;
-
+            case KeyEvent.KEYCODE_SEARCH:
+                if (down && repeatCount == 0 && !keyguardOn()) {
+                    switch(mSearchKeyBehavior) {
+                        case SEARCH_BEHAVIOR_TARGET_ACTIVITY: {
+                            launchTargetSearchActivity();
+                            return key_consumed;
+                        }
+                        case SEARCH_BEHAVIOR_DEFAULT_SEARCH:
+                        default:
+                            break;
+                    }
+                }
+                break;
             case KeyEvent.KEYCODE_SPACE:
                 // Handle keyboard layout switching. (META + SPACE)
                 if ((metaState & KeyEvent.META_META_MASK) == 0) {
@@ -3177,7 +3193,7 @@
                 }
                 if (down && repeatCount == 0) {
                     int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
-                    mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
+                    sendSwitchKeyboardLayout(event, direction);
                     return key_consumed;
                 }
                 break;
@@ -3427,7 +3443,7 @@
                     if (KeyEvent.metaStateHasModifiers(metaState & ~KeyEvent.META_SHIFT_MASK,
                             KeyEvent.META_CTRL_ON)) {
                         int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
-                        mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
+                        sendSwitchKeyboardLayout(event, direction);
                         return true;
                     }
                 }
@@ -3453,6 +3469,19 @@
         return false;
     }
 
+    private void sendSwitchKeyboardLayout(@NonNull KeyEvent event, int direction) {
+        mHandler.obtainMessage(MSG_SWITCH_KEYBOARD_LAYOUT, event.getDeviceId(),
+                direction).sendToTarget();
+    }
+
+    private void handleSwitchKeyboardLayout(int deviceId, int direction) {
+        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
+            InputMethodManagerInternal.get().switchKeyboardLayout(direction);
+        } else {
+            mWindowManagerFuncs.switchKeyboardLayout(deviceId, direction);
+        }
+    }
+
     private boolean interceptFallback(IBinder focusedToken, KeyEvent fallbackEvent,
             int policyFlags) {
         int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
@@ -6339,4 +6368,22 @@
         }
     }
 
+    private void launchTargetSearchActivity() {
+        Intent intent;
+        if (mSearchKeyTargetActivity != null) {
+            intent = new Intent();
+            intent.setComponent(mSearchKeyTargetActivity);
+        } else {
+            intent = new Intent(Intent.ACTION_WEB_SEARCH);
+        }
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        try {
+            startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
+        } catch (ActivityNotFoundException ignore) {
+            Slog.e(TAG, "Could not resolve activity with : "
+                    + intent.getComponent().flattenToString()
+                    + " name.");
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b83d509..bf8cbea 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -40,7 +40,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
 import android.app.AppOpsManager;
 import android.app.SynchronousUserSwitchObserver;
 import android.content.BroadcastReceiver;
@@ -317,7 +316,6 @@
     private SettingsObserver mSettingsObserver;
     private DreamManagerInternal mDreamManager;
     private LogicalLight mAttentionLight;
-    private ActivityManagerInternal mAmInternal;
 
     private final InattentiveSleepWarningController mInattentiveSleepWarningOverlayController;
     private final AmbientDisplaySuppressionController mAmbientDisplaySuppressionController;
@@ -1244,7 +1242,6 @@
             mDisplayManagerInternal = getLocalService(DisplayManagerInternal.class);
             mPolicy = getLocalService(WindowManagerPolicy.class);
             mBatteryManagerInternal = getLocalService(BatteryManagerInternal.class);
-            mAmInternal = getLocalService(ActivityManagerInternal.class);
             mAttentionDetector.systemReady(mContext);
 
             SensorManager sensorManager = new SystemSensorManager(mContext, mHandler.getLooper());
@@ -4088,8 +4085,9 @@
                     final UidState state = wakeLock.mUidState;
                     if (Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
                             Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
-                            (mAmInternal != null && !mAmInternal.canHoldWakeLocksInDeepDoze(
-                                    state.mUid, state.mProcState))) {
+                            state.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT &&
+                            state.mProcState >
+                                    ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE) {
                         disabled = true;
                     }
                 }
diff --git a/services/core/java/com/android/server/sensors/SensorManagerInternal.java b/services/core/java/com/android/server/sensors/SensorManagerInternal.java
index 41c2fbf..6c32ec2 100644
--- a/services/core/java/com/android/server/sensors/SensorManagerInternal.java
+++ b/services/core/java/com/android/server/sensors/SensorManagerInternal.java
@@ -17,6 +17,8 @@
 package com.android.server.sensors;
 
 import android.annotation.NonNull;
+import android.hardware.SensorDirectChannel;
+import android.os.ParcelFileDescriptor;
 
 import java.util.concurrent.Executor;
 
@@ -58,7 +60,7 @@
      * @return The sensor handle.
      */
     public abstract int createRuntimeSensor(int deviceId, int type, @NonNull String name,
-            @NonNull String vendor, @NonNull RuntimeSensorCallback callback);
+            @NonNull String vendor, int flags, @NonNull RuntimeSensorCallback callback);
 
     /**
      * Unregisters the sensor with the given handle from the framework.
@@ -98,9 +100,31 @@
     public interface RuntimeSensorCallback {
         /**
          * Invoked when the listeners of the runtime sensor have changed.
-         * Returns an error code if the invocation was unsuccessful, zero otherwise.
+         * Returns zero on success, negative error code otherwise.
          */
         int onConfigurationChanged(int handle, boolean enabled, int samplingPeriodMicros,
                 int batchReportLatencyMicros);
+
+        /**
+         * Invoked when a direct sensor channel has been created.
+         * Wraps the file descriptor in a {@link android.os.SharedMemory} object and passes it to
+         * the client process.
+         * Returns a positive identifier of the channel on success, negative error code otherwise.
+         */
+        int onDirectChannelCreated(ParcelFileDescriptor fd);
+
+        /**
+         * Invoked when a direct sensor channel has been destroyed.
+         */
+        void onDirectChannelDestroyed(int channelHandle);
+
+        /**
+         * Invoked when a direct sensor channel has been configured for a sensor.
+         * If the invocation is unsuccessful, a negative error code is returned.
+         * On success, the return value is zero if the rate level is {@code RATE_STOP}, and a
+         * positive report token otherwise.
+         */
+        int onDirectChannelConfigured(int channelHandle, int sensorHandle,
+                @SensorDirectChannel.RateLevel int rateLevel);
     }
 }
diff --git a/services/core/java/com/android/server/sensors/SensorService.java b/services/core/java/com/android/server/sensors/SensorService.java
index 9790659..1baa0a6 100644
--- a/services/core/java/com/android/server/sensors/SensorService.java
+++ b/services/core/java/com/android/server/sensors/SensorService.java
@@ -56,7 +56,8 @@
     private static native void unregisterProximityActiveListenerNative(long ptr);
 
     private static native int registerRuntimeSensorNative(long ptr, int deviceId, int type,
-            String name, String vendor, SensorManagerInternal.RuntimeSensorCallback callback);
+            String name, String vendor, int flags,
+            SensorManagerInternal.RuntimeSensorCallback callback);
     private static native void unregisterRuntimeSensorNative(long ptr, int handle);
     private static native boolean sendRuntimeSensorEventNative(long ptr, int handle, int type,
             long timestampNanos, float[] values);
@@ -95,9 +96,9 @@
     class LocalService extends SensorManagerInternal {
         @Override
         public int createRuntimeSensor(int deviceId, int type, @NonNull String name,
-                @NonNull String vendor, @NonNull RuntimeSensorCallback callback) {
+                @NonNull String vendor, int flags, @NonNull RuntimeSensorCallback callback) {
             synchronized (mLock) {
-                int handle = registerRuntimeSensorNative(mPtr, deviceId, type, name, vendor,
+                int handle = registerRuntimeSensorNative(mPtr, deviceId, type, name, vendor, flags,
                         callback);
                 mRuntimeSensorHandles.add(handle);
                 return handle;
diff --git a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
index 91c4a2f..1f7af41 100644
--- a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
+++ b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
@@ -42,6 +42,9 @@
     // TODO(b/230590090): Replace with public documentation once ready
     static final String DOC_LINK = "go/android-asm";
 
+    /** Used to determine which version of the ASM logic was used in logs while we iterate */
+    static final int ASM_VERSION = 6;
+
     private static final String NAMESPACE = NAMESPACE_WINDOW_MANAGER;
     private static final String KEY_ASM_PREFIX = "ActivitySecurity__";
     private static final String KEY_ASM_RESTRICTIONS_ENABLED = KEY_ASM_PREFIX
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 32dac49..ac07248 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -60,7 +60,6 @@
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
-import static com.android.server.wm.ActivityRecord.State.FINISHING;
 import static com.android.server.wm.ActivityRecord.State.RESUMED;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
@@ -75,6 +74,7 @@
 import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
 import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.ActivityTaskSupervisor.getApplicationLabel;
 import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_COMPONENT;
 import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_UID;
 import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_DEFAULT;
@@ -83,6 +83,7 @@
 import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_SAW_PERMISSION;
 import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_VISIBLE_WINDOW;
 import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK;
+import static com.android.server.wm.BackgroundActivityStartController.balCodeToString;
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY;
 import static com.android.server.wm.Task.REPARENT_MOVE_ROOT_TASK_TO_FRONT;
@@ -150,6 +151,9 @@
 import java.io.PrintWriter;
 import java.text.DateFormat;
 import java.util.Date;
+import java.util.StringJoiner;
+import java.util.function.Consumer;
+import java.util.function.Function;
 import java.util.function.Predicate;
 
 /**
@@ -1944,9 +1948,13 @@
             boolean passesAsmChecks = true;
             Task sourceTask = mSourceRecord.getTask();
 
-            // Don't allow launches into a new task if the current task is not foreground.
+            // Allow launching into a new task (or a task matching the launched activity's
+            // affinity) only if the current task is foreground or mutating its own task.
+            // The latter can happen eg. if caller uses NEW_TASK flag and the activity being
+            // launched matches affinity of source task.
             if (taskToFront) {
-                passesAsmChecks = sourceTask != null && sourceTask.isVisible();
+                passesAsmChecks = sourceTask != null
+                        && (sourceTask.isVisible() || sourceTask == targetTask);
             }
 
             if (passesAsmChecks) {
@@ -1967,8 +1975,7 @@
 
         // ASM rules have failed. Log why
         ActivityRecord targetTopActivity = targetTask == null ? null
-                : targetTask.getActivity(ar ->
-                        !ar.isState(FINISHING) && !ar.isAlwaysOnTop());
+                : targetTask.getActivity(ar -> !ar.finishing && !ar.isAlwaysOnTop());
 
         int action = newTask || mSourceRecord == null
                 ? FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__ACTIVITY_START_NEW_TASK
@@ -1999,7 +2006,7 @@
                 /* action */
                 action,
                 /* version */
-                4,
+                ActivitySecurityModelFeatureFlags.ASM_VERSION,
                 /* multi_window - we have our source not in the target task, but both are visible */
                 targetTask != null && mSourceRecord != null
                         && !targetTask.equals(mSourceRecord.getTask()) && targetTask.isVisible(),
@@ -2011,22 +2018,26 @@
                     .shouldRestrictActivitySwitch(mCallingUid)
                 && shouldBlockActivityStart;
 
+        String launchedFromPackageName = r.launchedFromPackage;
         if (ActivitySecurityModelFeatureFlags.shouldShowToast(mCallingUid)) {
+            String toastText = ActivitySecurityModelFeatureFlags.DOC_LINK
+                    + (blockActivityStartAndFeatureEnabled ? " blocked " : " would block ")
+                    + getApplicationLabel(mService.mContext.getPackageManager(),
+                        launchedFromPackageName);
             UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
-                    "Activity start from " + r.launchedFromPackage
-                            + (blockActivityStartAndFeatureEnabled ? " " : " would be ")
-                            + "blocked by " + ActivitySecurityModelFeatureFlags.DOC_LINK,
-                    Toast.LENGTH_SHORT).show());
+                    toastText, Toast.LENGTH_LONG).show());
+
+            logDebugInfoForActivitySecurity("Launch", r, targetTask, targetTopActivity,
+                    blockActivityStartAndFeatureEnabled, /* taskToFront */ taskToFront);
         }
 
-
         if (blockActivityStartAndFeatureEnabled) {
-            Slog.e(TAG, "Abort Launching r: " + r
+            Slog.e(TAG, "[ASM] Abort Launching r: " + r
                     + " as source: "
-                    + (mSourceRecord != null ? mSourceRecord : r.launchedFromPackage)
+                    + (mSourceRecord != null ? mSourceRecord : launchedFromPackageName)
                     + " is in background. New task: " + newTask
                     + ". Top activity: " + targetTopActivity
-                    + ". BAL Code: " + mBalCode);
+                    + ". BAL Code: " + balCodeToString(mBalCode));
 
             return false;
         }
@@ -2034,6 +2045,71 @@
         return true;
     }
 
+    /** Only called when an activity launch may be blocked, which should happen very rarely */
+    private void logDebugInfoForActivitySecurity(String action, ActivityRecord r, Task targetTask,
+            ActivityRecord targetTopActivity, boolean blockActivityStartAndFeatureEnabled,
+            boolean taskToFront) {
+        final String prefix = "[ASM] ";
+        Function<ActivityRecord, String> recordToString = (ar) -> {
+            if (ar == null) {
+                return null;
+            }
+            return (ar == mSourceRecord ? " [source]=> "
+                    : ar == targetTopActivity ? " [ top  ]=> "
+                            : ar == r ? " [target]=> "
+                                    : "         => ")
+                    + ar
+                    + " :: visible=" + ar.isVisible()
+                    + ", finishing=" + ar.isFinishing()
+                    + ", alwaysOnTop=" + ar.isAlwaysOnTop()
+                    + ", taskFragment=" + ar.getTaskFragment();
+        };
+
+        StringJoiner joiner = new StringJoiner("\n");
+        joiner.add(prefix + "------ Activity Security " + action + " Debug Logging Start ------");
+        joiner.add(prefix + "Block Enabled: " + blockActivityStartAndFeatureEnabled);
+        joiner.add(prefix + "ASM Version: " + ActivitySecurityModelFeatureFlags.ASM_VERSION);
+
+        boolean targetTaskMatchesSourceTask = targetTask != null
+                && mSourceRecord != null && mSourceRecord.getTask() == targetTask;
+
+        if (mSourceRecord == null) {
+            joiner.add(prefix + "Source Package: " + r.launchedFromPackage);
+            String realCallingPackage = mService.mContext.getPackageManager().getNameForUid(
+                    mRealCallingUid);
+            joiner.add(prefix + "Real Calling Uid Package: " + realCallingPackage);
+        } else {
+            joiner.add(prefix + "Source Record: " + recordToString.apply(mSourceRecord));
+            if (targetTaskMatchesSourceTask) {
+                joiner.add(prefix + "Source/Target Task: " + mSourceRecord.getTask());
+                joiner.add(prefix + "Source/Target Task Stack: ");
+            } else {
+                joiner.add(prefix + "Source Task: " + mSourceRecord.getTask());
+                joiner.add(prefix + "Source Task Stack: ");
+            }
+            mSourceRecord.getTask().forAllActivities((Consumer<ActivityRecord>)
+                    ar -> joiner.add(prefix + recordToString.apply(ar)));
+        }
+
+        joiner.add(prefix + "Target Task Top: " + recordToString.apply(targetTopActivity));
+        if (!targetTaskMatchesSourceTask) {
+            joiner.add(prefix + "Target Task: " + targetTask);
+            if (targetTask != null) {
+                joiner.add(prefix + "Target Task Stack: ");
+                targetTask.forAllActivities((Consumer<ActivityRecord>)
+                        ar -> joiner.add(prefix + recordToString.apply(ar)));
+            }
+        }
+
+        joiner.add(prefix + "Target Record: " + recordToString.apply(r));
+        joiner.add(prefix + "Intent: " + mIntent);
+        joiner.add(prefix + "TaskToFront: " + taskToFront);
+        joiner.add(prefix + "BalCode: " + balCodeToString(mBalCode));
+
+        joiner.add(prefix + "------ Activity Security " + action + " Debug Logging End ------");
+        Slog.i(TAG, joiner.toString());
+    }
+
     /**
      * Returns whether embedding of {@code starting} is allowed.
      *
@@ -2165,8 +2241,8 @@
             return;
         }
 
-        Predicate<ActivityRecord> isLaunchingOrLaunched = ar -> !ar.finishing && (ar.isUid(
-                startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid));
+        Predicate<ActivityRecord> isLaunchingOrLaunched = ar -> !ar.finishing
+                && (ar.isUid(startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid));
 
         // Return early if we know for sure we won't need to clear any activities by just checking
         // the top activity.
@@ -2202,7 +2278,10 @@
                             ? "Top activities cleared by "
                             : "Top activities would be cleared by ")
                             + ActivitySecurityModelFeatureFlags.DOC_LINK,
-                    Toast.LENGTH_SHORT).show());
+                    Toast.LENGTH_LONG).show());
+
+            logDebugInfoForActivitySecurity("Clear Top", mStartActivity, targetTask, targetTaskTop,
+                    shouldBlockActivityStart, /* taskToFront */ true);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 18be2a3..7d478b3 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -45,6 +45,7 @@
 import static android.content.pm.ConfigurationInfo.GL_ES_VERSION_UNDEFINED;
 import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
 import static android.content.pm.PackageManager.FEATURE_CANT_SAVE_STATE;
+import static android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP;
 import static android.content.pm.PackageManager.FEATURE_EXPANDED_PICTURE_IN_PICTURE;
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
 import static android.content.pm.PackageManager.FEATURE_LEANBACK;
@@ -401,6 +402,7 @@
     volatile WindowProcessController mHeavyWeightProcess;
     boolean mHasHeavyWeightFeature;
     boolean mHasLeanbackFeature;
+    boolean mHasCompanionDeviceSetupFeature;
     /** The process of the top most activity. */
     volatile WindowProcessController mTopApp;
     /**
@@ -859,6 +861,7 @@
             final PackageManager pm = mContext.getPackageManager();
             mHasHeavyWeightFeature = pm.hasSystemFeature(FEATURE_CANT_SAVE_STATE);
             mHasLeanbackFeature = pm.hasSystemFeature(FEATURE_LEANBACK);
+            mHasCompanionDeviceSetupFeature = pm.hasSystemFeature(FEATURE_COMPANION_DEVICE_SETUP);
             mVrController.onSystemReady();
             mRecentTasks.onSystemReadyLocked();
             mTaskSupervisor.onSystemReady();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index ef47b6e..df471c5 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -51,7 +51,6 @@
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
-import static com.android.server.wm.ActivityRecord.State.FINISHING;
 import static com.android.server.wm.ActivityRecord.State.PAUSED;
 import static com.android.server.wm.ActivityRecord.State.PAUSING;
 import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
@@ -103,6 +102,7 @@
 import android.app.servertransaction.ResumeActivityItem;
 import android.companion.virtual.VirtualDeviceManager;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
@@ -1236,11 +1236,16 @@
 
     int getDeviceIdForDisplayId(int displayId) {
         if (displayId == DEFAULT_DISPLAY || displayId == INVALID_DISPLAY)  {
-            return VirtualDeviceManager.DEVICE_ID_DEFAULT;
+            return Context.DEVICE_ID_DEFAULT;
         }
         if (mVirtualDeviceManager == null) {
-            mVirtualDeviceManager =
-                    mService.mContext.getSystemService(VirtualDeviceManager.class);
+            if (mService.mHasCompanionDeviceSetupFeature) {
+                mVirtualDeviceManager =
+                        mService.mContext.getSystemService(VirtualDeviceManager.class);
+            }
+            if (mVirtualDeviceManager == null) {
+                return Context.DEVICE_ID_DEFAULT;
+            }
         }
         return mVirtualDeviceManager.getDeviceIdForDisplayId(displayId);
     }
@@ -1636,50 +1641,6 @@
             // Prevent recursion.
             return;
         }
-        boolean shouldBlockActivitySwitchIfFeatureEnabled = false;
-        boolean wouldBlockActivitySwitchIgnoringFlags = false;
-        // We may have already checked that the callingUid has additional clearTask privileges, and
-        // cleared the calling identify. If so, we infer we do not need further restrictions here.
-        // TODO(b/263368846) Move to live with the rest of the ASM logic.
-        if (callingUid != SYSTEM_UID) {
-            Pair<Boolean, Boolean> pair = doesTopActivityMatchingUidExistForAsm(task,
-                    callingUid,
-                    null);
-            shouldBlockActivitySwitchIfFeatureEnabled = !pair.first;
-            wouldBlockActivitySwitchIgnoringFlags = !pair.second;
-            if (wouldBlockActivitySwitchIgnoringFlags) {
-                ActivityRecord topActivity =  task.getActivity(ar ->
-                        !ar.isState(FINISHING) && !ar.isAlwaysOnTop());
-                FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
-                        /* caller_uid */
-                        callingUid,
-                        /* caller_activity_class_name */
-                        callerActivityClassName,
-                        /* target_task_top_activity_uid */
-                        topActivity == null ? -1 : topActivity.getUid(),
-                        /* target_task_top_activity_class_name */
-                        topActivity == null ? null : topActivity.info.name,
-                        /* target_task_is_different */
-                        false,
-                        /* target_activity_uid */
-                        -1,
-                        /* target_activity_class_name */
-                        null,
-                        /* target_intent_action */
-                        null,
-                        /* target_intent_flags */
-                        0,
-                        /* action */
-                        FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__FINISH_TASK,
-                        /* version */
-                        3,
-                        /* multi_window */
-                        false,
-                        /* bal_code */
-                        -1
-                );
-            }
-        }
         task.mTransitionController.requestCloseTransitionIfNeeded(task);
         task.mInRemoveTask = true;
         try {
@@ -1690,33 +1651,107 @@
             if (task.isPersistable) {
                 mService.notifyTaskPersisterLocked(null, true);
             }
-            if (wouldBlockActivitySwitchIgnoringFlags) {
-                boolean restrictActivitySwitch = ActivitySecurityModelFeatureFlags
-                        .shouldRestrictActivitySwitch(callingUid)
-                        && shouldBlockActivitySwitchIfFeatureEnabled;
-                if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)) {
-                    UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
-                            (restrictActivitySwitch
-                                    ? "Returning home due to "
-                                    : "Would return home due to ")
-                                    + ActivitySecurityModelFeatureFlags.DOC_LINK,
-                            Toast.LENGTH_SHORT).show());
-                }
-
-                // If the activity switch should be restricted, return home rather than the
-                // previously top task, to prevent users from being confused which app they're
-                // viewing
-                if (restrictActivitySwitch) {
-                    Slog.w(TAG, "Return to home as source uid: " + callingUid
-                            + "is not on top of task t: " + task);
-                    task.getTaskDisplayArea().moveHomeActivityToTop("taskRemoved");
-                }
-            }
+            checkActivitySecurityForTaskClear(callingUid, task, callerActivityClassName);
         } finally {
             task.mInRemoveTask = false;
         }
     }
 
+    // TODO(b/263368846) Move to live with the rest of the ASM logic.
+    /**
+     * Returns home if the passed in callingUid is not top of the stack, rather than returning to
+     * previous task.
+     */
+    private void checkActivitySecurityForTaskClear(int callingUid, Task task,
+            String callerActivityClassName) {
+        // We may have already checked that the callingUid has additional clearTask privileges, and
+        // cleared the calling identify. If so, we infer we do not need further restrictions here.
+        if (callingUid == SYSTEM_UID) {
+            return;
+        }
+
+        TaskDisplayArea displayArea = task.getTaskDisplayArea();
+        if (displayArea == null) {
+            // If there is no associated display area, we can not return home.
+            return;
+        }
+
+        Pair<Boolean, Boolean> pair = doesTopActivityMatchingUidExistForAsm(task, callingUid, null);
+        boolean shouldBlockActivitySwitchIfFeatureEnabled = !pair.first;
+        boolean wouldBlockActivitySwitchIgnoringFlags = !pair.second;
+
+        if (!wouldBlockActivitySwitchIgnoringFlags) {
+            return;
+        }
+
+        ActivityRecord topActivity = task.getActivity(ar -> !ar.finishing && !ar.isAlwaysOnTop());
+        FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
+                /* caller_uid */
+                callingUid,
+                /* caller_activity_class_name */
+                callerActivityClassName,
+                /* target_task_top_activity_uid */
+                topActivity == null ? -1 : topActivity.getUid(),
+                /* target_task_top_activity_class_name */
+                topActivity == null ? null : topActivity.info.name,
+                /* target_task_is_different */
+                false,
+                /* target_activity_uid */
+                -1,
+                /* target_activity_class_name */
+                null,
+                /* target_intent_action */
+                null,
+                /* target_intent_flags */
+                0,
+                /* action */
+                FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__FINISH_TASK,
+                /* version */
+                ActivitySecurityModelFeatureFlags.ASM_VERSION,
+                /* multi_window */
+                false,
+                /* bal_code */
+                -1
+        );
+
+        boolean restrictActivitySwitch = ActivitySecurityModelFeatureFlags
+                .shouldRestrictActivitySwitch(callingUid)
+                && shouldBlockActivitySwitchIfFeatureEnabled;
+
+        PackageManager pm = mService.mContext.getPackageManager();
+        String callingPackage = pm.getNameForUid(callingUid);
+        final CharSequence callingLabel;
+        if (callingPackage == null) {
+            callingPackage = String.valueOf(callingUid);
+            callingLabel = callingPackage;
+        } else {
+            callingLabel = getApplicationLabel(pm, callingPackage);
+        }
+
+        if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)) {
+            Toast toast = Toast.makeText(mService.mContext,
+                    (ActivitySecurityModelFeatureFlags.DOC_LINK
+                            + (restrictActivitySwitch
+                            ? "returned home due to "
+                            : "would return home due to ")
+                            + callingLabel),
+                    Toast.LENGTH_LONG);
+            UiThread.getHandler().post(toast::show);
+        }
+
+        // If the activity switch should be restricted, return home rather than the
+        // previously top task, to prevent users from being confused which app they're
+        // viewing
+        if (restrictActivitySwitch) {
+            Slog.w(TAG, "[ASM] Return to home as source: " + callingPackage
+                    + " is not on top of task t: " + task);
+            displayArea.moveHomeActivityToTop("taskRemoved");
+        } else {
+            Slog.i(TAG, "[ASM] Would return to home as source: " + callingPackage
+                    + " is not on top of task t: " + task);
+        }
+    }
+
     /**
      *  For the purpose of ASM, ‘Top UID” for a task is defined as an activity UID
      *  1. Which is top of the stack in z-order
@@ -1743,7 +1778,7 @@
         // Consider the source activity, whether or not it is finishing. Do not consider any other
         // finishing activity.
         Predicate<ActivityRecord> topOfStackPredicate = (ar) -> ar.equals(sourceRecord)
-                || (!ar.isState(FINISHING) && !ar.isAlwaysOnTop());
+                || (!ar.finishing && !ar.isAlwaysOnTop());
 
         // Check top of stack (or the first task fragment for embedding).
         ActivityRecord topActivity = task.getActivity(topOfStackPredicate);
@@ -1777,6 +1812,16 @@
         return topActivity.allowCrossUidActivitySwitchFromBelow(uid);
     }
 
+    static CharSequence getApplicationLabel(PackageManager pm, String packageName) {
+        try {
+            ApplicationInfo launchedFromPackageInfo = pm.getApplicationInfo(
+                    packageName, PackageManager.ApplicationInfoFlags.of(0));
+            return pm.getApplicationLabel(launchedFromPackageInfo);
+        } catch (PackageManager.NameNotFoundException e) {
+            return packageName;
+        }
+    }
+
     void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) {
         if (removeFromRecents) {
             mRecentTasks.remove(task);
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 587138d..8fc3797 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -114,6 +114,35 @@
     /** Process belongs to a SDK sandbox */
     static final int BAL_ALLOW_SDK_SANDBOX = 10;
 
+    static String balCodeToString(@BalCode int balCode) {
+        switch (balCode) {
+            case BAL_ALLOW_ALLOWLISTED_COMPONENT:
+                return "BAL_ALLOW_ALLOWLISTED_COMPONENT";
+            case BAL_ALLOW_ALLOWLISTED_UID:
+                return "BAL_ALLOW_ALLOWLISTED_UID";
+            case BAL_ALLOW_DEFAULT:
+                return "BAL_ALLOW_DEFAULT";
+            case BAL_ALLOW_FOREGROUND:
+                return "BAL_ALLOW_FOREGROUND";
+            case BAL_ALLOW_GRACE_PERIOD:
+                return "BAL_ALLOW_GRACE_PERIOD";
+            case BAL_ALLOW_PENDING_INTENT:
+                return "BAL_ALLOW_PENDING_INTENT";
+            case BAL_ALLOW_PERMISSION:
+                return "BAL_ALLOW_PERMISSION";
+            case BAL_ALLOW_SAW_PERMISSION:
+                return "BAL_ALLOW_SAW_PERMISSION";
+            case BAL_ALLOW_SDK_SANDBOX:
+                return "BAL_ALLOW_SDK_SANDBOX";
+            case BAL_ALLOW_VISIBLE_WINDOW:
+                return "BAL_ALLOW_VISIBLE_WINDOW";
+            case BAL_BLOCK:
+                return "BAL_BLOCK";
+            default:
+                throw new IllegalArgumentException("Unexpected value: " + balCode);
+        }
+    }
+
     BackgroundActivityStartController(
             final ActivityTaskManagerService service, final ActivityTaskSupervisor supervisor) {
         mService = service;
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 25ce569..210a7d9 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -344,6 +344,19 @@
             }
         }
 
+        if (!attrs.isFullscreen() || attrs.getFitInsetsTypes() != 0) {
+            if (state == originalState) {
+                state = new InsetsState(originalState);
+            }
+            // Explicitly exclude floating windows from receiving caption insets. This is because we
+            // hard code caption insets for windows due to a synchronization issue that leads to
+            // flickering that bypasses insets frame calculation, which consequently needs us to
+            // remove caption insets from floating windows.
+            // TODO(b/254128050): Remove this workaround after we find a way to update window frames
+            //  and caption insets frames simultaneously.
+            state.removeSource(InsetsState.ITYPE_CAPTION_BAR);
+        }
+
         final SparseArray<WindowContainerInsetsSourceProvider> providers =
                 mStateController.getSourceProviders();
         final int windowType = attrs.type;
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index dc674c2..44b1cc8 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -862,10 +862,9 @@
         return mActivityRecord.mWmService.mContext.getResources();
     }
 
-    private void handleHorizontalDoubleTap(int x) {
-        // TODO(b/260857308): Investigate if enabling reachability for translucent activity
-        if (hasInheritedLetterboxBehavior() || !isHorizontalReachabilityEnabled()
-                || mActivityRecord.isInTransition()) {
+    @VisibleForTesting
+    void handleHorizontalDoubleTap(int x) {
+        if (!isHorizontalReachabilityEnabled() || mActivityRecord.isInTransition()) {
             return;
         }
 
@@ -903,10 +902,9 @@
         mActivityRecord.recomputeConfiguration();
     }
 
-    private void handleVerticalDoubleTap(int y) {
-        // TODO(b/260857308): Investigate if enabling reachability for translucent activity
-        if (hasInheritedLetterboxBehavior() || !isVerticalReachabilityEnabled()
-                || mActivityRecord.isInTransition()) {
+    @VisibleForTesting
+    void handleVerticalDoubleTap(int y) {
+        if (!isVerticalReachabilityEnabled() || mActivityRecord.isInTransition()) {
             return;
         }
 
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 97e0b1e..ce9bff8 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -948,7 +948,7 @@
         synchronized (mService.mGlobalLock) {
             WindowState windowState = mService.windowForClientLocked(this, window, false);
             if (windowState == null) {
-                Slog.e(TAG_WM,
+                Slog.i(TAG_WM,
                         "setOnBackInvokedCallback(): No window state for package:" + mPackageName);
             } else {
                 windowState.setOnBackInvokedCallbackInfo(callbackInfo);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cc81d52..0a833f4 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3512,10 +3512,7 @@
         info.isKeyguardOccluded =
             mAtmService.mKeyguardController.isDisplayOccluded(DEFAULT_DISPLAY);
 
-        info.startingWindowTypeParameter = activity.mStartingData != null
-                ? activity.mStartingData.mTypeParams
-                : (StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED
-                        | StartingWindowInfo.TYPE_PARAMETER_WINDOWLESS);
+        info.startingWindowTypeParameter = activity.mStartingData.mTypeParams;
         if ((info.startingWindowTypeParameter
                 & StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED) != 0) {
             final WindowState topMainWin = getWindow(w -> w.mAttrs.type == TYPE_BASE_APPLICATION);
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index b131365..3a30e4b 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.TaskInfo.cameraCompatControlStateToString;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
@@ -44,7 +43,6 @@
 import android.view.SurfaceControl;
 import android.window.ITaskOrganizer;
 import android.window.ITaskOrganizerController;
-import android.window.IWindowlessStartingSurfaceCallback;
 import android.window.SplashScreenView;
 import android.window.StartingWindowInfo;
 import android.window.StartingWindowRemovalInfo;
@@ -658,10 +656,9 @@
             info.splashScreenThemeResId = launchTheme;
         }
         info.taskSnapshot = taskSnapshot;
-        info.appToken = activity.token;
         // make this happen prior than prepare surface
         try {
-            lastOrganizer.addStartingWindow(info);
+            lastOrganizer.addStartingWindow(info, activity.token);
         } catch (RemoteException e) {
             Slog.e(TAG, "Exception sending onTaskStart callback", e);
             return false;
@@ -707,55 +704,6 @@
         }
     }
 
-    /**
-     * Create a starting surface which attach on a given surface.
-     * @param activity Target activity, this isn't necessary to be the top activity.
-     * @param root The root surface which the created surface will attach on.
-     * @param taskSnapshot Whether to draw snapshot.
-     * @param callback Called when surface is drawn and attached to the root surface.
-     * @return The taskId, this is a token and should be used to remove the surface, even if
-     *         the task was removed from hierarchy.
-     */
-    int addWindowlessStartingSurface(Task task, ActivityRecord activity, SurfaceControl root,
-            TaskSnapshot taskSnapshot, IWindowlessStartingSurfaceCallback callback) {
-        final Task rootTask = task.getRootTask();
-        if (rootTask == null) {
-            return INVALID_TASK_ID;
-        }
-        final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast();
-        if (lastOrganizer == null) {
-            return INVALID_TASK_ID;
-        }
-        final StartingWindowInfo info = task.getStartingWindowInfo(activity);
-        info.taskInfo.taskDescription = activity.taskDescription;
-        info.taskSnapshot = taskSnapshot;
-        info.windowlessStartingSurfaceCallback = callback;
-        info.rootSurface = root;
-        try {
-            lastOrganizer.addStartingWindow(info);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Exception sending addWindowlessStartingSurface ", e);
-            return INVALID_TASK_ID;
-        }
-        return task.mTaskId;
-    }
-
-    void removeWindowlessStartingSurface(int taskId, boolean immediately) {
-        final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast();
-        if (lastOrganizer == null || taskId == 0) {
-            return;
-        }
-        final StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo();
-        removalInfo.taskId = taskId;
-        removalInfo.windowlessSurface = true;
-        removalInfo.removeImmediately = immediately;
-        try {
-            lastOrganizer.removeStartingWindow(removalInfo);
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Exception sending removeWindowlessStartingSurface ", e);
-        }
-    }
-
     boolean copySplashScreenView(Task task) {
         final Task rootTask = task.getRootTask();
         if (rootTask == null) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index e56b679..aa10291 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -54,7 +54,6 @@
 import android.app.IApplicationThread;
 import android.app.ProfilerInfo;
 import android.app.servertransaction.ConfigurationChangeItem;
-import android.companion.virtual.VirtualDeviceManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -211,7 +210,7 @@
     /** Whether {@link #mLastReportedConfiguration} is deferred by the cached state. */
     private volatile boolean mHasCachedConfiguration;
 
-    private int mTopActivityDeviceId = VirtualDeviceManager.DEVICE_ID_DEFAULT;
+    private int mLastTopActivityDeviceId = Context.DEVICE_ID_DEFAULT;
     /**
      * Registered {@link DisplayArea} as a listener to override config changes. {@code null} if not
      * registered.
@@ -1412,8 +1411,9 @@
         // If deviceId for the top-activity changed, schedule passing it to the app process.
         boolean topActivityDeviceChanged = false;
         int deviceId = getTopActivityDeviceId();
-        if (deviceId != mTopActivityDeviceId) {
+        if (deviceId != mLastTopActivityDeviceId) {
             topActivityDeviceChanged = true;
+            mLastTopActivityDeviceId = deviceId;
         }
 
         final Configuration config = getConfiguration();
@@ -1432,15 +1432,12 @@
             return;
         }
 
-        // TODO(b/263402938): Add tests that capture the deviceId dispatch to the client.
-        mTopActivityDeviceId = deviceId;
-        dispatchConfiguration(config, topActivityDeviceChanged ? mTopActivityDeviceId
-                : VirtualDeviceManager.DEVICE_ID_INVALID);
+        dispatchConfiguration(config);
     }
 
     private int getTopActivityDeviceId() {
         ActivityRecord topActivity = getTopNonFinishingActivity();
-        int updatedDeviceId = mTopActivityDeviceId;
+        int updatedDeviceId = Context.DEVICE_ID_DEFAULT;
         if (topActivity != null && topActivity.mDisplayContent != null) {
             updatedDeviceId = mAtm.mTaskSupervisor.getDeviceIdForDisplayId(
                     topActivity.mDisplayContent.mDisplayId);
@@ -1485,10 +1482,6 @@
     }
 
     void dispatchConfiguration(Configuration config) {
-        dispatchConfiguration(config, getTopActivityDeviceId());
-    }
-
-    void dispatchConfiguration(Configuration config, int deviceId) {
         mHasPendingConfigurationChange = false;
         if (mThread == null) {
             if (Build.IS_DEBUGGABLE && mHasImeService) {
@@ -1515,16 +1508,10 @@
             }
         }
 
-        scheduleConfigurationChange(mThread, config, deviceId);
+        scheduleConfigurationChange(mThread, config);
     }
 
     private void scheduleConfigurationChange(IApplicationThread thread, Configuration config) {
-        // By default send invalid deviceId as no-op signal so it's not updated on the client side.
-        scheduleConfigurationChange(thread, config, VirtualDeviceManager.DEVICE_ID_INVALID);
-    }
-
-    private void scheduleConfigurationChange(IApplicationThread thread, Configuration config,
-            int deviceId) {
         ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending to proc %s new config %s", mName,
                 config);
         if (Build.IS_DEBUGGABLE && mHasImeService) {
@@ -1534,7 +1521,7 @@
         mHasCachedConfiguration = false;
         try {
             mAtm.getLifecycleManager().scheduleTransaction(thread,
-                    ConfigurationChangeItem.obtain(config, deviceId));
+                    ConfigurationChangeItem.obtain(config, mLastTopActivityDeviceId));
         } catch (Exception e) {
             Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change: " + mOwner, e);
         }
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index e2bdcdd..2ce86ad 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -179,6 +179,7 @@
         "android.hardware.power.stats@1.0",
         "android.hardware.power.stats-V1-ndk",
         "android.hardware.thermal@1.0",
+        "android.hardware.thermal-V1-ndk",
         "android.hardware.tv.input@1.0",
         "android.hardware.tv.input-V1-ndk",
         "android.hardware.vibrator-V2-cpp",
diff --git a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
index ed79352..7e0bb68 100644
--- a/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
+++ b/services/core/jni/com_android_server_HardwarePropertiesManagerService.cpp
@@ -16,27 +16,28 @@
 
 #define LOG_TAG "HardwarePropertiesManagerService-JNI"
 
-#include <nativehelper/JNIHelp.h>
-#include "jni.h"
-
-#include <math.h>
-#include <stdlib.h>
-
+#include <aidl/android/hardware/thermal/IThermal.h>
+#include <android/binder_manager.h>
 #include <android/hardware/thermal/1.0/IThermal.h>
+#include <math.h>
+#include <nativehelper/JNIHelp.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
 
 #include "core_jni_helpers.h"
+#include "jni.h"
 
 namespace android {
 
+using ::aidl::android::hardware::thermal::CoolingDevice;
+using ::aidl::android::hardware::thermal::IThermal;
+using ::aidl::android::hardware::thermal::Temperature;
+using ::aidl::android::hardware::thermal::TemperatureThreshold;
+using ::aidl::android::hardware::thermal::TemperatureType;
+using ::aidl::android::hardware::thermal::ThrottlingSeverity;
 using android::hidl::base::V1_0::IBase;
 using hardware::hidl_death_recipient;
 using hardware::hidl_vec;
-using hardware::thermal::V1_0::CoolingDevice;
-using hardware::thermal::V1_0::CpuUsage;
-using hardware::thermal::V1_0::IThermal;
-using hardware::thermal::V1_0::Temperature;
 using hardware::thermal::V1_0::ThermalStatus;
 using hardware::thermal::V1_0::ThermalStatusCode;
 template<typename T>
@@ -62,20 +63,28 @@
 
 static void getThermalHalLocked();
 static std::mutex gThermalHalMutex;
-static sp<IThermal> gThermalHal = nullptr;
+static sp<hardware::thermal::V1_0::IThermal> gThermalHidlHal = nullptr;
+static std::shared_ptr<IThermal> gThermalAidlHal = nullptr;
 
-// struct ThermalHalDeathRecipient;
-struct ThermalHalDeathRecipient : virtual public hidl_death_recipient {
-      // hidl_death_recipient interface
-      virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override {
-          std::lock_guard<std::mutex> lock(gThermalHalMutex);
-          ALOGE("ThermalHAL just died");
-          gThermalHal = nullptr;
-          getThermalHalLocked();
-      }
+struct ThermalHidlHalDeathRecipient : virtual public hidl_death_recipient {
+    // hidl_death_recipient interface
+    virtual void serviceDied(uint64_t cookie, const wp<IBase> &who) override {
+        std::lock_guard<std::mutex> lock(gThermalHalMutex);
+        ALOGE("Thermal HAL just died");
+        gThermalHidlHal = nullptr;
+        getThermalHalLocked();
+    }
 };
 
-sp<ThermalHalDeathRecipient> gThermalHalDeathRecipient = nullptr;
+static void onThermalAidlBinderDied(void *cookie) {
+    std::lock_guard<std::mutex> lock(gThermalHalMutex);
+    ALOGE("Thermal AIDL HAL just died");
+    gThermalAidlHal = nullptr;
+    getThermalHalLocked();
+}
+
+sp<ThermalHidlHalDeathRecipient> gThermalHidlHalDeathRecipient = nullptr;
+ndk::ScopedAIBinder_DeathRecipient gThermalAidlDeathRecipient;
 
 // ----------------------------------------------------------------------------
 
@@ -85,27 +94,49 @@
 
 // The caller must be holding gThermalHalMutex.
 static void getThermalHalLocked() {
-    if (gThermalHal != nullptr) {
+    if (gThermalAidlHal || gThermalHidlHal) {
+        return;
+    }
+    const std::string thermalInstanceName = std::string(IThermal::descriptor) + "/default";
+    if (AServiceManager_isDeclared(thermalInstanceName.c_str())) {
+        auto binder = AServiceManager_waitForService(thermalInstanceName.c_str());
+        auto thermalAidlService = IThermal::fromBinder(ndk::SpAIBinder(binder));
+        if (thermalAidlService) {
+            gThermalAidlHal = thermalAidlService;
+            if (gThermalAidlDeathRecipient.get() == nullptr) {
+                gThermalAidlDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(
+                        AIBinder_DeathRecipient_new(onThermalAidlBinderDied));
+            }
+            auto linked = AIBinder_linkToDeath(thermalAidlService->asBinder().get(),
+                                               gThermalAidlDeathRecipient.get(), nullptr);
+            if (linked != STATUS_OK) {
+                ALOGW("Failed to link to death (AIDL): %d", linked);
+                gThermalAidlHal = nullptr;
+            }
+        } else {
+            ALOGE("Unable to get Thermal AIDL service");
+        }
         return;
     }
 
-    gThermalHal = IThermal::getService();
+    ALOGI("Thermal AIDL service is not declared, trying HIDL");
+    gThermalHidlHal = hardware::thermal::V1_0::IThermal::getService();
 
-    if (gThermalHal == nullptr) {
+    if (gThermalHidlHal == nullptr) {
         ALOGE("Unable to get Thermal service.");
     } else {
-        if (gThermalHalDeathRecipient == nullptr) {
-            gThermalHalDeathRecipient = new ThermalHalDeathRecipient();
+        if (gThermalHidlHalDeathRecipient == nullptr) {
+            gThermalHidlHalDeathRecipient = new ThermalHidlHalDeathRecipient();
         }
-        hardware::Return<bool> linked = gThermalHal->linkToDeath(
-            gThermalHalDeathRecipient, 0x451F /* cookie */);
+        hardware::Return<bool> linked =
+                gThermalHidlHal->linkToDeath(gThermalHidlHalDeathRecipient, 0x451F /* cookie */);
         if (!linked.isOk()) {
             ALOGE("Transaction error in linking to ThermalHAL death: %s",
-            linked.description().c_str());
-            gThermalHal = nullptr;
+                  linked.description().c_str());
+            gThermalHidlHal = nullptr;
         } else if (!linked) {
             ALOGW("Unable to link to ThermalHal death notifications");
-            gThermalHal = nullptr;
+            gThermalHidlHal = nullptr;
         } else {
             ALOGD("Link to death notification successful");
         }
@@ -117,17 +148,27 @@
     getThermalHalLocked();
 }
 
-static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
-    std::lock_guard<std::mutex> lock(gThermalHalMutex);
-    getThermalHalLocked();
-    if (gThermalHal == nullptr) {
-        ALOGE("Couldn't get fan speeds because of HAL error.");
+static jfloatArray getFanSpeedsAidl(JNIEnv *env) {
+    std::vector<CoolingDevice> list;
+    auto status = gThermalAidlHal->getCoolingDevices(&list);
+    if (!status.isOk()) {
+        ALOGE("getFanSpeeds failed status: %s", status.getMessage());
         return env->NewFloatArray(0);
     }
+    float values[list.size()];
+    for (size_t i = 0; i < list.size(); ++i) {
+        values[i] = list[i].value;
+    }
+    jfloatArray fanSpeeds = env->NewFloatArray(list.size());
+    env->SetFloatArrayRegion(fanSpeeds, 0, list.size(), values);
+    return fanSpeeds;
+}
 
-    hidl_vec<CoolingDevice> list;
-    Return<void> ret = gThermalHal->getCoolingDevices(
-            [&list](ThermalStatus status, hidl_vec<CoolingDevice> devices) {
+static jfloatArray getFanSpeedsHidl(JNIEnv *env) {
+    hidl_vec<hardware::thermal::V1_0::CoolingDevice> list;
+    Return<void> ret = gThermalHidlHal->getCoolingDevices(
+            [&list](ThermalStatus status,
+                    hidl_vec<hardware::thermal::V1_0::CoolingDevice> devices) {
                 if (status.code == ThermalStatusCode::SUCCESS) {
                     list = std::move(devices);
                 } else {
@@ -137,9 +178,9 @@
             });
 
     if (!ret.isOk()) {
-        ALOGE("getCoolingDevices failed status: %s", ret.description().c_str());
+        ALOGE("getFanSpeeds failed status: %s", ret.description().c_str());
+        return env->NewFloatArray(0);
     }
-
     float values[list.size()];
     for (size_t i = 0; i < list.size(); ++i) {
         values[i] = list[i].currentValue;
@@ -149,17 +190,79 @@
     return fanSpeeds;
 }
 
-static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type,
-                                               int source) {
+static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
     std::lock_guard<std::mutex> lock(gThermalHalMutex);
     getThermalHalLocked();
-    if (gThermalHal == nullptr) {
-        ALOGE("Couldn't get device temperatures because of HAL error.");
+    if (!gThermalHidlHal && !gThermalAidlHal) {
+        ALOGE("Couldn't get fan speeds because of HAL error.");
         return env->NewFloatArray(0);
     }
-    hidl_vec<Temperature> list;
-    Return<void> ret = gThermalHal->getTemperatures(
-            [&list](ThermalStatus status, hidl_vec<Temperature> temperatures) {
+    if (gThermalAidlHal) {
+        return getFanSpeedsAidl(env);
+    }
+    return getFanSpeedsHidl(env);
+}
+
+static jfloatArray getDeviceTemperaturesAidl(JNIEnv *env, int type, int source) {
+    jfloat *values;
+    size_t length = 0;
+    if (source == TEMPERATURE_CURRENT) {
+        std::vector<Temperature> list;
+        auto status =
+                gThermalAidlHal->getTemperaturesWithType(static_cast<TemperatureType>(type), &list);
+
+        if (!status.isOk()) {
+            ALOGE("getDeviceTemperatures failed status: %s", status.getMessage());
+            return env->NewFloatArray(0);
+        }
+        values = new jfloat[list.size()];
+        for (const auto &temp : list) {
+            if (static_cast<int>(temp.type) == type) {
+                values[length++] = finalizeTemperature(temp.value);
+            }
+        }
+    } else if (source == TEMPERATURE_THROTTLING_BELOW_VR_MIN) {
+        values = new jfloat[1];
+        values[length++] = gUndefinedTemperature;
+    } else {
+        std::vector<TemperatureThreshold> list;
+        auto status =
+                gThermalAidlHal->getTemperatureThresholdsWithType(static_cast<TemperatureType>(
+                                                                          type),
+                                                                  &list);
+
+        if (!status.isOk()) {
+            ALOGE("getDeviceTemperatures failed status: %s", status.getMessage());
+            return env->NewFloatArray(0);
+        }
+        values = new jfloat[list.size()];
+        for (auto &t : list) {
+            if (static_cast<int>(t.type) == type) {
+                switch (source) {
+                    case TEMPERATURE_THROTTLING:
+                        values[length++] =
+                                finalizeTemperature(t.hotThrottlingThresholds[static_cast<int>(
+                                        ThrottlingSeverity::SEVERE)]);
+                        break;
+                    case TEMPERATURE_SHUTDOWN:
+                        values[length++] =
+                                finalizeTemperature(t.hotThrottlingThresholds[static_cast<int>(
+                                        ThrottlingSeverity::SHUTDOWN)]);
+                        break;
+                }
+            }
+        }
+    }
+    jfloatArray deviceTemps = env->NewFloatArray(length);
+    env->SetFloatArrayRegion(deviceTemps, 0, length, values);
+    return deviceTemps;
+}
+
+static jfloatArray getDeviceTemperaturesHidl(JNIEnv *env, int type, int source) {
+    hidl_vec<hardware::thermal::V1_0::Temperature> list;
+    Return<void> ret = gThermalHidlHal->getTemperatures(
+            [&list](ThermalStatus status,
+                    hidl_vec<hardware::thermal::V1_0::Temperature> temperatures) {
                 if (status.code == ThermalStatusCode::SUCCESS) {
                     list = std::move(temperatures);
                 } else {
@@ -170,9 +273,9 @@
 
     if (!ret.isOk()) {
         ALOGE("getDeviceTemperatures failed status: %s", ret.description().c_str());
+        return env->NewFloatArray(0);
     }
-
-    jfloat values[list.size()];
+    float values[list.size()];
     size_t length = 0;
     for (size_t i = 0; i < list.size(); ++i) {
         if (static_cast<int>(list[i].type) == type) {
@@ -197,16 +300,34 @@
     return deviceTemps;
 }
 
+static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type,
+                                               int source) {
+    std::lock_guard<std::mutex> lock(gThermalHalMutex);
+    getThermalHalLocked();
+    if (!gThermalHidlHal && !gThermalAidlHal) {
+        ALOGE("Couldn't get device temperatures because of HAL error.");
+        return env->NewFloatArray(0);
+    }
+    if (gThermalAidlHal) {
+        return getDeviceTemperaturesAidl(env, type, source);
+    }
+    return getDeviceTemperaturesHidl(env, type, source);
+}
+
 static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) {
     std::lock_guard<std::mutex> lock(gThermalHalMutex);
     getThermalHalLocked();
-    if (gThermalHal == nullptr || !gCpuUsageInfoClassInfo.initMethod) {
+    if (gThermalAidlHal) {
+        ALOGW("getCpuUsages is not supported");
+        return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
+    }
+    if (gThermalHidlHal == nullptr || !gCpuUsageInfoClassInfo.initMethod) {
         ALOGE("Couldn't get CPU usages because of HAL error.");
         return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
     }
-    hidl_vec<CpuUsage> list;
-    Return<void> ret = gThermalHal->getCpuUsages(
-            [&list](ThermalStatus status, hidl_vec<CpuUsage> cpuUsages) {
+    hidl_vec<hardware::thermal::V1_0::CpuUsage> list;
+    Return<void> ret = gThermalHidlHal->getCpuUsages(
+            [&list](ThermalStatus status, hidl_vec<hardware::thermal::V1_0::CpuUsage> cpuUsages) {
                 if (status.code == ThermalStatusCode::SUCCESS) {
                     list = std::move(cpuUsages);
                 } else {
@@ -217,6 +338,7 @@
 
     if (!ret.isOk()) {
         ALOGE("getCpuUsages failed status: %s", ret.description().c_str());
+        return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
     }
 
     jobjectArray cpuUsages = env->NewObjectArray(list.size(), gCpuUsageInfoClassInfo.clazz,
diff --git a/services/core/jni/com_android_server_sensor_SensorService.cpp b/services/core/jni/com_android_server_sensor_SensorService.cpp
index 356e9a9..a916b64 100644
--- a/services/core/jni/com_android_server_sensor_SensorService.cpp
+++ b/services/core/jni/com_android_server_sensor_SensorService.cpp
@@ -17,10 +17,13 @@
 #define LOG_TAG "NativeSensorService"
 
 #include <android-base/properties.h>
+#include <android_os_NativeHandle.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <core_jni_helpers.h>
+#include <cutils/native_handle.h>
 #include <cutils/properties.h>
 #include <jni.h>
+#include <nativehelper/JNIPlatformHelp.h>
 #include <sensorservice/SensorService.h>
 #include <string.h>
 #include <utils/Log.h>
@@ -28,6 +31,8 @@
 
 #include <mutex>
 
+#include "android_util_Binder.h"
+
 #define PROXIMITY_ACTIVE_CLASS \
     "com/android/server/sensors/SensorManagerInternal$ProximityActiveListener"
 
@@ -38,7 +43,10 @@
 
 static JavaVM* sJvm = nullptr;
 static jmethodID sMethodIdOnProximityActive;
-static jmethodID sMethodIdOnConfigurationChanged;
+static jmethodID sMethodIdRuntimeSensorOnConfigurationChanged;
+static jmethodID sMethodIdRuntimeSensorOnDirectChannelCreated;
+static jmethodID sMethodIdRuntimeSensorOnDirectChannelDestroyed;
+static jmethodID sMethodIdRuntimeSensorOnDirectChannelConfigured;
 
 class NativeSensorService {
 public:
@@ -47,7 +55,7 @@
     void registerProximityActiveListener();
     void unregisterProximityActiveListener();
     jint registerRuntimeSensor(JNIEnv* env, jint deviceId, jint type, jstring name, jstring vendor,
-                               jobject callback);
+                               jint flags, jobject callback);
     void unregisterRuntimeSensor(jint handle);
     jboolean sendRuntimeSensorEvent(JNIEnv* env, jint handle, jint type, jlong timestamp,
                                     jfloatArray values);
@@ -74,6 +82,9 @@
 
         status_t onConfigurationChanged(int32_t handle, bool enabled, int64_t samplingPeriodNs,
                                         int64_t batchReportLatencyNs) override;
+        int onDirectChannelCreated(int fd) override;
+        void onDirectChannelDestroyed(int channelHandle) override;
+        int onDirectChannelConfigured(int channelHandle, int sensorHandle, int rateLevel) override;
 
     private:
         jobject mCallback;
@@ -108,7 +119,7 @@
 }
 
 jint NativeSensorService::registerRuntimeSensor(JNIEnv* env, jint deviceId, jint type, jstring name,
-                                                jstring vendor, jobject callback) {
+                                                jstring vendor, jint flags, jobject callback) {
     if (mService == nullptr) {
         ALOGD("Dropping registerRuntimeSensor, sensor service not available.");
         return -1;
@@ -119,6 +130,11 @@
             .vendor = env->GetStringUTFChars(vendor, 0),
             .version = sizeof(sensor_t),
             .type = type,
+#ifdef __LP64__
+            .flags = static_cast<uint64_t>(flags),
+#else
+            .flags = static_cast<uint32_t>(flags),
+#endif
     };
 
     sp<RuntimeSensorCallbackDelegate> callbackDelegate(
@@ -234,12 +250,39 @@
 status_t NativeSensorService::RuntimeSensorCallbackDelegate::onConfigurationChanged(
         int32_t handle, bool enabled, int64_t samplingPeriodNs, int64_t batchReportLatencyNs) {
     auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
-    return jniEnv->CallIntMethod(mCallback, sMethodIdOnConfigurationChanged,
+    return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnConfigurationChanged,
                                  static_cast<jint>(handle), static_cast<jboolean>(enabled),
                                  static_cast<jint>(ns2us(samplingPeriodNs)),
                                  static_cast<jint>(ns2us(batchReportLatencyNs)));
 }
 
+int NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelCreated(int fd) {
+    if (fd <= 0) {
+        return 0;
+    }
+    auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+    jobject jfd = jniCreateFileDescriptor(jniEnv, fd);
+    jobject parcelFileDescriptor = newParcelFileDescriptor(jniEnv, jfd);
+    return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelCreated,
+                                 parcelFileDescriptor);
+}
+
+void NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelDestroyed(
+        int channelHandle) {
+    auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+    return jniEnv->CallVoidMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelDestroyed,
+                                  static_cast<jint>(channelHandle));
+}
+
+int NativeSensorService::RuntimeSensorCallbackDelegate::onDirectChannelConfigured(int channelHandle,
+                                                                                  int sensorHandle,
+                                                                                  int rateLevel) {
+    auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
+    return jniEnv->CallIntMethod(mCallback, sMethodIdRuntimeSensorOnDirectChannelConfigured,
+                                 static_cast<jint>(channelHandle), static_cast<jint>(sensorHandle),
+                                 static_cast<jint>(rateLevel));
+}
+
 static jlong startSensorServiceNative(JNIEnv* env, jclass, jobject listener) {
     NativeSensorService* service = new NativeSensorService(env, listener);
     return reinterpret_cast<jlong>(service);
@@ -256,9 +299,10 @@
 }
 
 static jint registerRuntimeSensorNative(JNIEnv* env, jclass, jlong ptr, jint deviceId, jint type,
-                                        jstring name, jstring vendor, jobject callback) {
+                                        jstring name, jstring vendor, jint flags,
+                                        jobject callback) {
     auto* service = reinterpret_cast<NativeSensorService*>(ptr);
-    return service->registerRuntimeSensor(env, deviceId, type, name, vendor, callback);
+    return service->registerRuntimeSensor(env, deviceId, type, name, vendor, flags, callback);
 }
 
 static void unregisterRuntimeSensorNative(JNIEnv* env, jclass, jlong ptr, jint handle) {
@@ -280,7 +324,7 @@
         {"unregisterProximityActiveListenerNative", "(J)V",
          reinterpret_cast<void*>(unregisterProximityActiveListenerNative)},
         {"registerRuntimeSensorNative",
-         "(JIILjava/lang/String;Ljava/lang/String;L" RUNTIME_SENSOR_CALLBACK_CLASS ";)I",
+         "(JIILjava/lang/String;Ljava/lang/String;IL" RUNTIME_SENSOR_CALLBACK_CLASS ";)I",
          reinterpret_cast<void*>(registerRuntimeSensorNative)},
         {"unregisterRuntimeSensorNative", "(JI)V",
          reinterpret_cast<void*>(unregisterRuntimeSensorNative)},
@@ -293,8 +337,17 @@
     jclass listenerClass = FindClassOrDie(env, PROXIMITY_ACTIVE_CLASS);
     sMethodIdOnProximityActive = GetMethodIDOrDie(env, listenerClass, "onProximityActive", "(Z)V");
     jclass runtimeSensorCallbackClass = FindClassOrDie(env, RUNTIME_SENSOR_CALLBACK_CLASS);
-    sMethodIdOnConfigurationChanged =
+    sMethodIdRuntimeSensorOnConfigurationChanged =
             GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onConfigurationChanged", "(IZII)I");
+    sMethodIdRuntimeSensorOnDirectChannelCreated =
+            GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelCreated",
+                             "(Landroid/os/ParcelFileDescriptor;)I");
+    sMethodIdRuntimeSensorOnDirectChannelDestroyed =
+            GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelDestroyed", "(I)V");
+    sMethodIdRuntimeSensorOnDirectChannelConfigured =
+            GetMethodIDOrDie(env, runtimeSensorCallbackClass, "onDirectChannelConfigured",
+                             "(III)I");
+
     return jniRegisterNativeMethods(env, "com/android/server/sensors/SensorService", methods,
                                     NELEM(methods));
 }
diff --git a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
index f8b1e6fc..6bf18c2 100644
--- a/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/ClearRequestSession.java
@@ -29,6 +29,9 @@
 import android.service.credentials.CredentialProviderInfo;
 import android.util.Log;
 
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+
 import java.util.ArrayList;
 
 /**
@@ -119,18 +122,21 @@
             // TODO: Differentiate btw cancelled and false
             mChosenProviderMetric.setChosenProviderStatus(
                     MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_SUCCESS);
-            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
         try {
             mClientCallback.onSuccess();
-            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_SUCCESS);
         } catch (RemoteException e) {
             mChosenProviderMetric.setChosenProviderStatus(
                     MetricUtilities.METRICS_PROVIDER_STATUS_FINAL_FAILURE);
             Log.i(TAG, "Issue while propagating the response to the client");
-            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
+            logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_FAILURE);
         }
         finishSession(/*propagateCancellation=*/false);
     }
@@ -139,7 +145,8 @@
         Log.i(TAG, "respondToClientWithErrorAndFinish");
         if (isSessionCancelled()) {
             // TODO: Differentiate btw cancelled and false
-            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
@@ -148,7 +155,8 @@
         } catch (RemoteException e) {
             e.printStackTrace();
         }
-        logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
+        logApiCall(ApiName.CLEAR_CREDENTIAL, /* apiStatus */
+                ApiStatus.METRICS_API_STATUS_FAILURE);
         finishSession(/*propagateCancellation=*/false);
     }
 
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index 4dd0c84..656e44c 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -36,6 +36,9 @@
 import android.service.credentials.CredentialProviderInfo;
 import android.util.Log;
 
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+
 import java.util.ArrayList;
 
 /**
@@ -141,16 +144,19 @@
         }
         if (isSessionCancelled()) {
             // TODO: Differentiate btw cancelled and false
-            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
         try {
             mClientCallback.onResponse(response);
-            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_SUCCESS);
         } catch (RemoteException e) {
             Log.i(TAG, "Issue while responding to client: " + e.getMessage());
-            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
+            logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_FAILURE);
         }
         finishSession(/*propagateCancellation=*/false);
     }
@@ -163,7 +169,8 @@
         }
         if (isSessionCancelled()) {
             // TODO: Differentiate btw cancelled and false
-            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.CREATE_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
@@ -172,10 +179,20 @@
         } catch (RemoteException e) {
             Log.i(TAG, "Issue while responding to client: " + e.getMessage());
         }
-        logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
+        logFailureOrUserCancel(errorType);
         finishSession(/*propagateCancellation=*/false);
     }
 
+    private void logFailureOrUserCancel(String errorType) {
+        if (CreateCredentialException.TYPE_USER_CANCELED.equals(errorType)) {
+            logApiCall(ApiName.CREATE_CREDENTIAL,
+                    /* apiStatus */ ApiStatus.METRICS_API_STATUS_USER_CANCELED);
+        } else {
+            logApiCall(ApiName.CREATE_CREDENTIAL,
+                    /* apiStatus */ ApiStatus.METRICS_API_STATUS_FAILURE);
+        }
+    }
+
     @Override
     public void onProviderStatusChanged(ProviderSession.Status status,
             ComponentName componentName) {
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index 7a4e7df..41ae911 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -64,6 +64,8 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
 import com.android.server.infra.AbstractMasterSystemService;
 import com.android.server.infra.SecureSettingsServiceNameResolver;
 
@@ -84,7 +86,7 @@
  */
 public final class CredentialManagerService
         extends AbstractMasterSystemService<
-                CredentialManagerService, CredentialManagerServiceImpl> {
+        CredentialManagerService, CredentialManagerServiceImpl> {
 
     private static final String TAG = "CredManSysService";
     private static final String DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API =
@@ -267,7 +269,8 @@
         final long origId = Binder.clearCallingIdentity();
         try {
             return DeviceConfig.getBoolean(
-                DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API, false);
+                    DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_DESC_API,
+                    false);
         } finally {
             Binder.restoreCallingIdentity(origId);
         }
@@ -317,8 +320,8 @@
         Set<Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult>> result =
                 new HashSet<>();
 
-        for (CredentialDescriptionRegistry.FilterResult filterResult: filterResults) {
-            for (CredentialOption credentialOption: options) {
+        for (CredentialDescriptionRegistry.FilterResult filterResult : filterResults) {
+            for (CredentialOption credentialOption : options) {
                 if (filterResult.mFlattenedRequest.equals(credentialOption
                         .getCredentialRetrievalData()
                         .getString(CredentialOption.FLATTENED_REQUEST))) {
@@ -364,13 +367,13 @@
         CallingAppInfo callingAppInfo;
         try {
             packageInfo =
-                getContext()
-                    .getPackageManager()
-                    .getPackageInfoAsUser(
-                            realPackageName,
-                        PackageManager.PackageInfoFlags.of(
-                            PackageManager.GET_SIGNING_CERTIFICATES),
-                        userId);
+                    getContext()
+                            .getPackageManager()
+                            .getPackageInfoAsUser(
+                                    realPackageName,
+                                    PackageManager.PackageInfoFlags.of(
+                                            PackageManager.GET_SIGNING_CERTIFICATES),
+                                    userId);
             callingAppInfo = new CallingAppInfo(realPackageName, packageInfo.signingInfo, origin);
         } catch (PackageManager.NameNotFoundException e) {
             Log.i(TAG, "Issue while retrieving signatureInfo : " + e.getMessage());
@@ -421,41 +424,41 @@
             if (isCredentialDescriptionApiEnabled()) {
                 List<CredentialOption> optionsThatRequireActiveCredentials =
                         request.getCredentialOptions().stream()
-                        .filter(
-                            getCredentialOption ->
-                                !TextUtils.isEmpty(
-                                    getCredentialOption
-                                        .getCredentialRetrievalData()
-                                        .getString(
-                                            CredentialOption
-                                                .FLATTENED_REQUEST,
-                                            null)))
-                        .toList();
+                                .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();
+                                .filter(
+                                        getCredentialOption ->
+                                                TextUtils.isEmpty(
+                                                        getCredentialOption
+                                                                .getCredentialRetrievalData()
+                                                                .getString(
+                                                                        CredentialOption
+                                                                                .FLATTENED_REQUEST,
+                                                                        null)))
+                                .toList();
 
                 List<ProviderSession> sessionsWithoutRemoteService =
                         initiateProviderSessionsWithActiveContainers(
-                        session,
-                        getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
+                                session,
+                                getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
 
                 List<ProviderSession> sessionsWithRemoteService =
                         initiateProviderSessions(
-                        session,
-                        optionsThatDoNotRequireActiveCredentials.stream()
-                            .map(CredentialOption::getType)
-                            .collect(Collectors.toList()));
+                                session,
+                                optionsThatDoNotRequireActiveCredentials.stream()
+                                        .map(CredentialOption::getType)
+                                        .collect(Collectors.toList()));
 
                 Set<ProviderSession> all = new LinkedHashSet<>();
                 all.addAll(sessionsWithRemoteService);
@@ -465,11 +468,11 @@
             } else {
                 // Initiate all provider sessions
                 providerSessions =
-                    initiateProviderSessions(
-                        session,
-                        request.getCredentialOptions().stream()
-                            .map(CredentialOption::getType)
-                            .collect(Collectors.toList()));
+                        initiateProviderSessions(
+                                session,
+                                request.getCredentialOptions().stream()
+                                        .map(CredentialOption::getType)
+                                        .collect(Collectors.toList()));
             }
 
             if (providerSessions.isEmpty()) {
@@ -481,8 +484,8 @@
                     Log.i(
                             TAG,
                             "Issue invoking onError on IGetCredentialCallback "
-                                + "callback: "
-                                + e.getMessage());
+                                    + "callback: "
+                                    + e.getMessage());
                 }
             }
             providerSessions.forEach(ProviderSession::invokeSession);
@@ -538,8 +541,8 @@
                     Log.i(
                             TAG,
                             "Issue invoking onError on ICreateCredentialCallback "
-                                + "callback: "
-                                + e.getMessage());
+                                    + "callback: "
+                                    + e.getMessage());
                 }
             }
 
@@ -654,13 +657,17 @@
                     if (serviceComponentName.equals(componentName)) {
                         if (!s.getServicePackageName().equals(callingPackage)) {
                             // The component name and the package name do not match.
+                            MetricUtilities.logApiCalled(
+                                    ApiName.IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE,
+                                    ApiStatus.METRICS_API_STATUS_FAILURE, callingUid);
                             Log.w(
                                     TAG,
                                     "isEnabledCredentialProviderService: Component name does not"
                                             + " match package name.");
                             return false;
                         }
-
+                        MetricUtilities.logApiCalled(ApiName.IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE,
+                                ApiStatus.METRICS_API_STATUS_SUCCESS, callingUid);
                         return true;
                     }
                 }
@@ -745,7 +752,7 @@
             enforceCallingPackage(callingPackage, Binder.getCallingUid());
 
             List<CredentialProviderInfo> services =
-                getServicesForCredentialDescription(UserHandle.getCallingUserId());
+                    getServicesForCredentialDescription(UserHandle.getCallingUserId());
 
             List<String> providers =
                     services.stream()
@@ -801,7 +808,7 @@
             enforceCallingPackage(callingPackage, Binder.getCallingUid());
 
             List<CredentialProviderInfo> services =
-                getServicesForCredentialDescription(UserHandle.getCallingUserId());
+                    getServicesForCredentialDescription(UserHandle.getCallingUserId());
 
             List<String> providers =
                     services.stream()
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index 5e16771..ce26c88 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -34,6 +34,9 @@
 import android.service.credentials.CredentialProviderInfo;
 import android.util.Log;
 
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+
 import java.util.ArrayList;
 
 /**
@@ -44,7 +47,6 @@
         IGetCredentialCallback>
         implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> {
     private static final String TAG = "GetRequestSession";
-
     public GetRequestSession(Context context, int userId, int callingUid,
             IGetCredentialCallback callback, GetCredentialRequest request,
             CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
@@ -118,16 +120,19 @@
         }
         if (isSessionCancelled()) {
             // TODO: Differentiate btw cancelled and false
-            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+            logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
         try {
             mClientCallback.onResponse(response);
-            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ true);
+            logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_SUCCESS);
         } catch (RemoteException e) {
             Log.i(TAG, "Issue while responding to client with a response : " + e.getMessage());
-            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+            logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_FAILURE);
         }
         finishSession(/*propagateCancellation=*/false);
     }
@@ -138,7 +143,8 @@
             return;
         }
         if (isSessionCancelled()) {
-            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+            logApiCall(ApiName.GET_CREDENTIAL, /* apiStatus */
+                    ApiStatus.METRICS_API_STATUS_CLIENT_CANCELED);
             finishSession(/*propagateCancellation=*/true);
             return;
         }
@@ -148,10 +154,20 @@
         } catch (RemoteException e) {
             Log.i(TAG, "Issue while responding to client with error : " + e.getMessage());
         }
-        logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
+        logFailureOrUserCancel(errorType);
         finishSession(/*propagateCancellation=*/false);
     }
 
+    private void logFailureOrUserCancel(String errorType) {
+        if (GetCredentialException.TYPE_USER_CANCELED.equals(errorType)) {
+            logApiCall(ApiName.GET_CREDENTIAL,
+                    /* apiStatus */ ApiStatus.METRICS_API_STATUS_USER_CANCELED);
+        } else {
+            logApiCall(ApiName.GET_CREDENTIAL,
+                    /* apiStatus */ ApiStatus.METRICS_API_STATUS_FAILURE);
+        }
+    }
+
     @Override
     public void onUiCancellation(boolean isUserCancellation) {
         if (isUserCancellation) {
@@ -173,6 +189,12 @@
     public void onProviderStatusChanged(ProviderSession.Status status,
             ComponentName componentName) {
         Log.i(TAG, "in onStatusChanged with status: " + status);
+        // Auth entry was selected, and it did not have any underlying credentials
+        if (status == ProviderSession.Status.NO_CREDENTIALS_FROM_AUTH_ENTRY) {
+            handleEmptyAuthenticationSelection(componentName);
+            return;
+        }
+        // For any other status, we check if all providers are done and then invoke UI if needed
         if (!isAnyProviderPending()) {
             // If all provider responses have been received, we can either need the UI,
             // or we need to respond with error. The only other case is the entry being
@@ -186,4 +208,34 @@
             }
         }
     }
+
+    private void handleEmptyAuthenticationSelection(ComponentName componentName) {
+        // Update auth entry statuses across different provider sessions
+        mProviders.keySet().forEach(key -> {
+            ProviderGetSession session = (ProviderGetSession) mProviders.get(key);
+            if (!session.mComponentName.equals(componentName)) {
+                session.updateAuthEntriesStatusFromAnotherSession();
+            }
+        });
+
+        // Invoke UI since it needs to show a snackbar if last auth entry, or a status on each
+        // auth entries along with other valid entries
+        getProviderDataAndInitiateUi();
+
+        // Respond to client if all auth entries are empty and nothing else to show on the UI
+        if (providerDataContainsEmptyAuthEntriesOnly()) {
+            respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
+                    "No credentials available");
+        }
+    }
+
+    private boolean providerDataContainsEmptyAuthEntriesOnly() {
+        for (String key : mProviders.keySet()) {
+            ProviderGetSession session = (ProviderGetSession) mProviders.get(key);
+            if (!session.containsEmptyAuthEntriesOnly()) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/services/credentials/java/com/android/server/credentials/MetricUtilities.java b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
index 27d9836d..f75a9b6 100644
--- a/services/credentials/java/com/android/server/credentials/MetricUtilities.java
+++ b/services/credentials/java/com/android/server/credentials/MetricUtilities.java
@@ -16,14 +16,6 @@
 
 package com.android.server.credentials;
 
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
-import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
 import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_FAILURE;
 import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_SUCCESS;
 import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_QUERY_FAILURE;
@@ -35,6 +27,14 @@
 import android.content.pm.PackageManager;
 import android.util.Log;
 
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
+import com.android.server.credentials.metrics.CandidateProviderMetric;
+import com.android.server.credentials.metrics.ChosenProviderMetric;
+
+import java.util.Map;
+
 /**
  * For all future metric additions, this will contain their names for local usage after importing
  * from {@link com.android.internal.util.FrameworkStatsLog}.
@@ -43,24 +43,10 @@
 
     private static final String TAG = "MetricUtilities";
 
-    // Metrics constants
-    protected static final int METRICS_API_NAME_UNKNOWN =
-            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
-    protected static final int METRICS_API_NAME_GET_CREDENTIAL =
-            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
-    protected static final int METRICS_API_NAME_CREATE_CREDENTIAL =
-            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
-    protected static final int METRICS_API_NAME_CLEAR_CREDENTIAL =
-            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
-    // TODO add isEnabled
-    protected static final int METRICS_API_STATUS_SUCCESS =
-            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
-    protected static final int METRICS_API_STATUS_FAILURE =
-            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
-    protected static final int METRICS_API_STATUS_CLIENT_CANCEL =
-            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
-    protected static final int METRICS_API_STATUS_USER_CANCEL =
-            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
+    private static final int DEFAULT_INT_32 = -1;
+    private static final int[] DEFAULT_REPEATED_INT_32 = new int[0];
+
+    // Metrics constants TODO(b/269290341) migrate to enums eventually to improve
     protected static final int METRICS_PROVIDER_STATUS_FINAL_FAILURE =
             CREDENTIAL_MANAGER_API_CALLED__CANDIDATE_PROVIDER_STATUS__PROVIDER_FINAL_FAILURE;
     protected static final int METRICS_PROVIDER_STATUS_QUERY_FAILURE =
@@ -77,6 +63,7 @@
      * This retrieves the uid of any package name, given a context and a component name for the
      * package. By default, if the desired package uid cannot be found, it will fall back to a
      * bogus uid.
+     *
      * @return the uid of a given package
      */
     protected static int getPackageUid(Context context, ComponentName componentName) {
@@ -92,4 +79,75 @@
         return sessUid;
     }
 
+    /**
+     * The most common logging helper, handles the overall status of the API request with the
+     * provider status and latencies. Other versions of this method may be more useful depending
+     * on the situation, as this is geared towards the logging of {@link ProviderSession} types.
+     *
+     * @param apiName              the api type to log
+     * @param apiStatus            the api status to log
+     * @param providers            a map with known providers
+     * @param callingUid           the calling UID of the client app
+     * @param chosenProviderMetric the metric data type of the final chosen provider
+     */
+    protected static void logApiCalled(ApiName apiName, ApiStatus apiStatus,
+            Map<String, ProviderSession> providers, int callingUid,
+            ChosenProviderMetric chosenProviderMetric) {
+        var providerSessions = providers.values();
+        int providerSize = providerSessions.size();
+        int[] candidateUidList = new int[providerSize];
+        int[] candidateQueryRoundTripTimeList = new int[providerSize];
+        int[] candidateStatusList = new int[providerSize];
+        int index = 0;
+        for (var session : providerSessions) {
+            CandidateProviderMetric metric = session.mCandidateProviderMetric;
+            candidateUidList[index] = metric.getCandidateUid();
+            candidateQueryRoundTripTimeList[index] = metric.getQueryLatencyMs();
+            candidateStatusList[index] = metric.getProviderQueryStatus();
+            index++;
+        }
+        FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
+                /* api_name */apiName.getMetricCode(),
+                /* caller_uid */ callingUid,
+                /* api_status */ apiStatus.getMetricCode(),
+                /* repeated_candidate_provider_uid */ candidateUidList,
+                /* repeated_candidate_provider_round_trip_time_query_microseconds */
+                candidateQueryRoundTripTimeList,
+                /* repeated_candidate_provider_status */ candidateStatusList,
+                /* chosen_provider_uid */ chosenProviderMetric.getChosenUid(),
+                /* chosen_provider_round_trip_time_overall_microseconds */
+                chosenProviderMetric.getEntireProviderLatencyMs(),
+                /* chosen_provider_final_phase_microseconds */
+                chosenProviderMetric.getFinalPhaseLatencyMs(),
+                /* chosen_provider_status */ chosenProviderMetric.getChosenProviderStatus());
+    }
+
+    /**
+     * This is useful just to record an API calls' final event, and for no other purpose. It will
+     * contain default values for all other optional parameters.
+     *
+     * TODO(b/271135048) - given space requirements, this may be a good candidate for another atom
+     *
+     * @param apiName    the api name to log
+     * @param apiStatus  the status to log
+     * @param callingUid the calling uid
+     */
+    protected static void logApiCalled(ApiName apiName, ApiStatus apiStatus,
+            int callingUid) {
+        FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
+                /* api_name */apiName.getMetricCode(),
+                /* caller_uid */ callingUid,
+                /* api_status */ apiStatus.getMetricCode(),
+                /* repeated_candidate_provider_uid */  DEFAULT_REPEATED_INT_32,
+                /* repeated_candidate_provider_round_trip_time_query_microseconds */
+                DEFAULT_REPEATED_INT_32,
+                /* repeated_candidate_provider_status */ DEFAULT_REPEATED_INT_32,
+                /* chosen_provider_uid */ DEFAULT_INT_32,
+                /* chosen_provider_round_trip_time_overall_microseconds */
+                DEFAULT_INT_32,
+                /* chosen_provider_final_phase_microseconds */
+                DEFAULT_INT_32,
+                /* chosen_provider_status */ DEFAULT_INT_32);
+    }
+
 }
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index 12074c7..6498b6a 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -241,13 +241,14 @@
                 if (additionalContentReceived) {
                     Log.i(TAG, "Additional content received - removing authentication entry");
                     mProviderResponseDataHandler.removeAuthenticationAction(entryKey);
+                    if (!mProviderResponseDataHandler.isEmptyResponse()) {
+                        updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
+                    }
                 } else {
                     Log.i(TAG, "Additional content not received");
                     mProviderResponseDataHandler
                             .updateAuthEntryWithNoCredentialsReceived(entryKey);
-                }
-                if (!mProviderResponseDataHandler.isEmptyResponse()) {
-                    updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
+                    updateStatusAndInvokeCallback(Status.NO_CREDENTIALS_FROM_AUTH_ENTRY);
                 }
                 break;
             case REMOTE_ENTRY_KEY:
@@ -414,25 +415,8 @@
     /** Returns true if either an exception or a response is found. */
     private void onActionEntrySelected(ProviderPendingIntentResponse
             providerPendingIntentResponse) {
-        // Action entry is expected to either contain the final GetCredentialResponse, or it is
-        // also acceptable if it does not contain anything. In the second case, we re-show this
-        // action on the UI.
-        if (providerPendingIntentResponse == null) {
-            Log.i(TAG, "providerPendingIntentResponse is null");
-            return;
-        }
-
-        GetCredentialException exception = maybeGetPendingIntentException(
-                providerPendingIntentResponse);
-        if (exception != null) {
-            invokeCallbackWithError(exception.getType(), exception.getMessage());
-        }
-        GetCredentialResponse response = PendingIntentResultHandler
-                .extractGetCredentialResponse(
-                        providerPendingIntentResponse.getResultData());
-        if (response != null) {
-            mCallbacks.onFinalResponseReceived(mComponentName, response);
-        }
+        Log.i(TAG, "onActionEntrySelected");
+        onCredentialEntrySelected(providerPendingIntentResponse);
     }
 
 
@@ -449,11 +433,32 @@
 
     /**
      * 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.
+     * we send back a TYPE_NO_CREDENTIAL error as to the developer.
      */
     private void invokeCallbackOnInternalInvalidState() {
         mCallbacks.onFinalErrorReceived(mComponentName,
-                GetCredentialException.TYPE_UNKNOWN, null);
+                GetCredentialException.TYPE_NO_CREDENTIAL, null);
+    }
+
+    /** Update auth entries status based on an auth entry selected from a different session. */
+    public void updateAuthEntriesStatusFromAnotherSession() {
+        // Pass null for entryKey if the auth entry selected belongs to a different session
+        mProviderResponseDataHandler.updateAuthEntryWithNoCredentialsReceived(/*entryKey=*/null);
+    }
+
+    /** Returns true if the provider response contains empty auth entries only, false otherwise. **/
+    public boolean containsEmptyAuthEntriesOnly() {
+        // We do not consider action entries here because if actions are the only entries,
+        // we don't show the UI
+        return mProviderResponseDataHandler.mUiCredentialEntries.isEmpty()
+                && mProviderResponseDataHandler.mUiRemoteEntry == null
+                && mProviderResponseDataHandler.mUiAuthenticationEntries
+                .values().stream().allMatch(
+                        e -> e.second.getStatus() == AuthenticationEntry
+                                .STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT
+                                || e.second.getStatus()
+                                == AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_MOST_RECENT
+        );
     }
 
     private class ProviderResponseDataHandler {
@@ -610,7 +615,12 @@
                     ? null : mUiCredentialEntries.get(entryKey).first;
         }
 
-        public void updateAuthEntryWithNoCredentialsReceived(String entryKey) {
+        public void updateAuthEntryWithNoCredentialsReceived(@Nullable String entryKey) {
+            if (entryKey == null) {
+                // Auth entry from a different provider was selected by the user.
+                updatePreviousMostRecentAuthEntry();
+                return;
+            }
             updatePreviousMostRecentAuthEntry();
             updateMostRecentAuthEntry(entryKey);
         }
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index 2f9d578..ecddcf3 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -66,7 +66,8 @@
      * on the credMan UI.
      */
     public static boolean isUiInvokingStatus(Status status) {
-        return status == Status.CREDENTIALS_RECEIVED || status == Status.SAVE_ENTRIES_RECEIVED;
+        return status == Status.CREDENTIALS_RECEIVED || status == Status.SAVE_ENTRIES_RECEIVED
+                || status == Status.NO_CREDENTIALS_FROM_AUTH_ENTRY;
     }
 
     /**
@@ -140,7 +141,7 @@
         PENDING_INTENT_INVOKED,
         CREDENTIAL_RECEIVED_FROM_SELECTION,
         SAVE_ENTRIES_RECEIVED, CANCELED,
-        NO_CREDENTIALS, EMPTY_RESPONSE, COMPLETE
+        NO_CREDENTIALS, EMPTY_RESPONSE, NO_CREDENTIALS_FROM_AUTH_ENTRY, COMPLETE
     }
 
     /** Converts exception to a provider session status. */
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index f0d05c5..86e05cf 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -16,12 +16,7 @@
 
 package com.android.server.credentials;
 
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_CLEAR_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_CREATE_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_GET_CREDENTIAL;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_NAME_UNKNOWN;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_STATUS_FAILURE;
-import static com.android.server.credentials.MetricUtilities.METRICS_API_STATUS_SUCCESS;
+import static com.android.server.credentials.MetricUtilities.logApiCalled;
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
@@ -39,7 +34,8 @@
 import android.util.Log;
 
 import com.android.internal.R;
-import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.credentials.metrics.ApiName;
+import com.android.server.credentials.metrics.ApiStatus;
 import com.android.server.credentials.metrics.CandidateProviderMetric;
 import com.android.server.credentials.metrics.ChosenProviderMetric;
 
@@ -162,50 +158,10 @@
         }
         return false;
     }
-    // TODO: move these definitions to a separate logging focused class.
-    enum RequestType {
-        GET_CREDENTIALS,
-        CREATE_CREDENTIALS,
-        CLEAR_CREDENTIALS,
-    }
 
-    private static int getApiNameFromRequestType(RequestType requestType) {
-        switch (requestType) {
-            case GET_CREDENTIALS:
-                return METRICS_API_NAME_GET_CREDENTIAL;
-            case CREATE_CREDENTIALS:
-                return METRICS_API_NAME_CREATE_CREDENTIAL;
-            case CLEAR_CREDENTIALS:
-                return METRICS_API_NAME_CLEAR_CREDENTIAL;
-            default:
-                return METRICS_API_NAME_UNKNOWN;
-        }
-    }
-
-    protected void logApiCalled(RequestType requestType, boolean isSuccessfulOverall) {
-        var providerSessions = mProviders.values();
-        int providerSize = providerSessions.size();
-        int[] candidateUidList = new int[providerSize];
-        int[] candidateQueryRoundTripTimeList = new int[providerSize];
-        int[] candidateStatusList = new int[providerSize];
-        int index = 0;
-        for (var session : providerSessions) {
-            CandidateProviderMetric metric = session.mCandidateProviderMetric;
-            candidateUidList[index] = metric.getCandidateUid();
-            candidateQueryRoundTripTimeList[index] = metric.getQueryLatencyMs();
-            candidateStatusList[index] = metric.getProviderQueryStatus();
-            index++;
-        }
-        FrameworkStatsLog.write(FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED,
-                /* api_name */getApiNameFromRequestType(requestType), /* caller_uid */
-                mCallingUid, /* api_status */
-                isSuccessfulOverall ? METRICS_API_STATUS_SUCCESS : METRICS_API_STATUS_FAILURE,
-                candidateUidList,
-                candidateQueryRoundTripTimeList,
-                candidateStatusList, mChosenProviderMetric.getChosenUid(),
-                mChosenProviderMetric.getEntireProviderLatencyMs(),
-                mChosenProviderMetric.getFinalPhaseLatencyMs(),
-                mChosenProviderMetric.getChosenProviderStatus());
+    protected void logApiCall(ApiName apiName, ApiStatus apiStatus) {
+        logApiCalled(apiName, apiStatus, mProviders, mCallingUid,
+                mChosenProviderMetric);
     }
 
     protected boolean isSessionCancelled() {
@@ -216,7 +172,7 @@
      * Returns true if at least one provider is ready for UI invocation, and no
      * provider is pending a response.
      */
-    boolean isUiInvocationNeeded() {
+    protected boolean isUiInvocationNeeded() {
         for (ProviderSession session : mProviders.values()) {
             if (ProviderSession.isUiInvokingStatus(session.getStatus())) {
                 return true;
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ApiName.java b/services/credentials/java/com/android/server/credentials/metrics/ApiName.java
new file mode 100644
index 0000000..d4b51df
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/ApiName.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.server.credentials.metrics;
+
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN;
+
+public enum ApiName {
+    UNKNOWN(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_UNKNOWN),
+    GET_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_GET_CREDENTIAL),
+    CREATE_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CREATE_CREDENTIAL),
+    CLEAR_CREDENTIAL(CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_CLEAR_CREDENTIAL),
+    IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE(
+            CREDENTIAL_MANAGER_API_CALLED__API_NAME__API_NAME_IS_ENABLED_CREDENTIAL_PROVIDER_SERVICE
+    );
+
+    private final int mInnerMetricCode;
+
+    ApiName(int innerMetricCode) {
+        this.mInnerMetricCode = innerMetricCode;
+    }
+
+    /**
+     * Gives the West-world version of the metric name.
+     *
+     * @return a code corresponding to the west world metric name
+     */
+    public int getMetricCode() {
+        return this.mInnerMetricCode;
+    }
+}
diff --git a/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java b/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java
new file mode 100644
index 0000000..36a1f2d
--- /dev/null
+++ b/services/credentials/java/com/android/server/credentials/metrics/ApiStatus.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.metrics;
+
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS;
+import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED;
+
+public enum ApiStatus {
+    METRICS_API_STATUS_SUCCESS(CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_SUCCESS),
+    METRICS_API_STATUS_FAILURE(CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_FAILURE),
+    METRICS_API_STATUS_CLIENT_CANCELED(
+            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_CLIENT_CANCELED),
+    METRICS_API_STATUS_USER_CANCELED(
+            CREDENTIAL_MANAGER_API_CALLED__API_STATUS__API_STATUS_USER_CANCELED);
+
+    private final int mInnerMetricCode;
+
+    ApiStatus(int innerMetricCode) {
+        this.mInnerMetricCode = innerMetricCode;
+    }
+
+    /**
+     * Gives the West-world version of the metric name.
+     *
+     * @return a code corresponding to the west world metric name
+     */
+    public int getMetricCode() {
+        return this.mInnerMetricCode;
+    }
+}
diff --git a/services/incremental/TEST_MAPPING b/services/incremental/TEST_MAPPING
index 3976a70..be7feb5 100644
--- a/services/incremental/TEST_MAPPING
+++ b/services/incremental/TEST_MAPPING
@@ -16,13 +16,13 @@
     },
     {
       "name": "service.incremental_test"
+    },
+    {
+      "name": "CtsInstalledLoadingProgressHostTests"
     }
   ],
   "presubmit-large": [
     {
-      "name": "CtsInstalledLoadingProgressHostTests"
-    },
-    {
       "name": "CtsContentTestCases",
       "options": [
         {
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index 17e1744..0ca4dfc 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -113,7 +113,6 @@
     private static final long USAGE_STATS_QUERY_INTERVAL_SEC = 120L;
     @VisibleForTesting
     static final int MAX_CACHED_RECENT_SHORTCUTS = 30;
-    private static final int DEBOUNCE_LENGTH_MS = 500;
 
     private final Context mContext;
     private final Injector mInjector;
@@ -130,7 +129,6 @@
     private final List<PeopleService.ConversationsListener> mConversationsListeners =
             new ArrayList<>(1);
     private final Handler mHandler;
-    private final PerPackageThrottler mShortcutsThrottler;
 
     private ContentObserver mCallLogContentObserver;
     private ContentObserver mMmsSmsContentObserver;
@@ -142,17 +140,14 @@
     private ConversationStatusExpirationBroadcastReceiver mStatusExpReceiver;
 
     public DataManager(Context context) {
-        this(context, new Injector(), BackgroundThread.get().getLooper(),
-                new PerPackageThrottlerImpl(BackgroundThread.getHandler(), DEBOUNCE_LENGTH_MS));
+        this(context, new Injector(), BackgroundThread.get().getLooper());
     }
 
-    DataManager(Context context, Injector injector, Looper looper,
-            PerPackageThrottler shortcutsThrottler) {
+    DataManager(Context context, Injector injector, Looper looper) {
         mContext = context;
         mInjector = injector;
         mScheduledExecutor = mInjector.createScheduledExecutor();
         mHandler = new Handler(looper);
-        mShortcutsThrottler = shortcutsThrottler;
     }
 
     /** Initialization. Called when the system services are up running. */
@@ -856,12 +851,12 @@
         // pair of <package name, conversation info>
         List<Pair<String, ConversationInfo>> cachedConvos = new ArrayList<>();
         userData.forAllPackages(packageData -> {
-            packageData.forAllConversations(conversationInfo -> {
-                if (isEligibleForCleanUp(conversationInfo)) {
-                    cachedConvos.add(
-                            Pair.create(packageData.getPackageName(), conversationInfo));
-                }
-            });
+                packageData.forAllConversations(conversationInfo -> {
+                    if (isEligibleForCleanUp(conversationInfo)) {
+                        cachedConvos.add(
+                                Pair.create(packageData.getPackageName(), conversationInfo));
+                    }
+                });
         });
         if (cachedConvos.size() <= targetCachedCount) {
             return;
@@ -872,8 +867,8 @@
                 numToUncache + 1,
                 Comparator.comparingLong((Pair<String, ConversationInfo> pair) ->
                         Math.max(
-                                pair.second.getLastEventTimestamp(),
-                                pair.second.getCreationTimestamp())).reversed());
+                            pair.second.getLastEventTimestamp(),
+                            pair.second.getCreationTimestamp())).reversed());
         for (Pair<String, ConversationInfo> cached : cachedConvos) {
             if (hasActiveNotifications(cached.first, userId, cached.second.getShortcutId())) {
                 continue;
@@ -1109,35 +1104,26 @@
         @Override
         public void onShortcutsAddedOrUpdated(@NonNull String packageName,
                 @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
-            mShortcutsThrottler.scheduleDebounced(
-                    new Pair<>(packageName, user.getIdentifier()),
-                    () -> {
-                        PackageData packageData = getPackage(packageName, user.getIdentifier());
-                        List<ShortcutInfo> queriedShortcuts = getShortcuts(packageName,
-                                user.getIdentifier(), null);
-                        boolean hasCachedShortcut = false;
-                        for (ShortcutInfo shortcut : queriedShortcuts) {
-                            if (ShortcutHelper.isConversationShortcut(
-                                    shortcut, mShortcutServiceInternal, user.getIdentifier())) {
-                                if (shortcut.isCached()) {
-                                    ConversationInfo info = packageData != null
-                                            ? packageData.getConversationInfo(shortcut.getId())
-                                            : null;
-                                    if (info == null
-                                            || !info.isShortcutCachedForNotification()) {
-                                        hasCachedShortcut = true;
-                                    }
-                                }
-                                addOrUpdateConversationInfo(shortcut);
+            mInjector.getBackgroundExecutor().execute(() -> {
+                PackageData packageData = getPackage(packageName, user.getIdentifier());
+                for (ShortcutInfo shortcut : shortcuts) {
+                    if (ShortcutHelper.isConversationShortcut(
+                            shortcut, mShortcutServiceInternal, user.getIdentifier())) {
+                        if (shortcut.isCached()) {
+                            ConversationInfo conversationInfo = packageData != null
+                                    ? packageData.getConversationInfo(shortcut.getId()) : null;
+                            if (conversationInfo == null
+                                    || !conversationInfo.isShortcutCachedForNotification()) {
+                                // This is a newly cached shortcut. Clean up the existing cached
+                                // shortcuts to ensure the cache size is under the limit.
+                                cleanupCachedShortcuts(user.getIdentifier(),
+                                        MAX_CACHED_RECENT_SHORTCUTS - 1);
                             }
                         }
-                        // Added at least one new conversation. Uncache older existing cached
-                        // shortcuts to ensure the cache size is under the limit.
-                        if (hasCachedShortcut) {
-                            cleanupCachedShortcuts(user.getIdentifier(),
-                                    MAX_CACHED_RECENT_SHORTCUTS);
-                        }
-                    });
+                        addOrUpdateConversationInfo(shortcut);
+                    }
+                }
+            });
         }
 
         @Override
diff --git a/services/people/java/com/android/server/people/data/PerPackageThrottler.java b/services/people/java/com/android/server/people/data/PerPackageThrottler.java
deleted file mode 100644
index 3d6cd84..0000000
--- a/services/people/java/com/android/server/people/data/PerPackageThrottler.java
+++ /dev/null
@@ -1,28 +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.people.data;
-
-import android.util.Pair;
-
-/** The interface for throttling expensive runnables per package. */
-interface PerPackageThrottler {
-    /**
-     * Schedule a runnable to run in the future, and debounce runnables for same {@code pkgUserId}
-     * that occur until that future has run.
-     */
-    void scheduleDebounced(Pair<String, Integer> pkgUserId, Runnable runnable);
-}
diff --git a/services/people/java/com/android/server/people/data/PerPackageThrottlerImpl.java b/services/people/java/com/android/server/people/data/PerPackageThrottlerImpl.java
deleted file mode 100644
index fa5a67b..0000000
--- a/services/people/java/com/android/server/people/data/PerPackageThrottlerImpl.java
+++ /dev/null
@@ -1,52 +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.people.data;
-
-import android.os.Handler;
-import android.util.Pair;
-
-import java.util.HashSet;
-
-/**
- * A class that implements a per-package throttler that prevents a runnable from executing more than
- * once every {@code debounceTime}.
- */
-public class PerPackageThrottlerImpl implements PerPackageThrottler {
-    private final Handler mBackgroundHandler;
-    private final int mDebounceTime;
-    private final HashSet<Pair<String, Integer>> mPkgScheduledTasks = new HashSet<>();
-
-    PerPackageThrottlerImpl(Handler backgroundHandler, int debounceTime) {
-        mBackgroundHandler = backgroundHandler;
-        mDebounceTime = debounceTime;
-    }
-
-    @Override
-    public synchronized void scheduleDebounced(
-            Pair<String, Integer> pkgUserId, Runnable runnable) {
-        if (mPkgScheduledTasks.contains(pkgUserId)) {
-            return;
-        }
-        mPkgScheduledTasks.add(pkgUserId);
-        mBackgroundHandler.postDelayed(() -> {
-            synchronized (this) {
-                mPkgScheduledTasks.remove(pkgUserId);
-                runnable.run();
-            }
-        }, mDebounceTime);
-    }
-}
diff --git a/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java b/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java
new file mode 100644
index 0000000..0ad4184
--- /dev/null
+++ b/services/robotests/src/com/android/server/media/AudioPoliciesBluetoothRouteControllerTest.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.Application;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.media.MediaRoute2Info;
+import android.os.UserHandle;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowBluetoothAdapter;
+import org.robolectric.shadows.ShadowBluetoothDevice;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioPoliciesBluetoothRouteControllerTest {
+
+    private static final String DEVICE_ADDRESS_UNKNOWN = ":unknown:ip:address:";
+    private static final String DEVICE_ADDRESS_SAMPLE_1 = "30:59:8B:E4:C6:35";
+    private static final String DEVICE_ADDRESS_SAMPLE_2 = "0D:0D:A6:FF:8D:B6";
+    private static final String DEVICE_ADDRESS_SAMPLE_3 = "2D:9B:0C:C2:6F:78";
+    private static final String DEVICE_ADDRESS_SAMPLE_4 = "66:88:F9:2D:A8:1E";
+
+    private Context mContext;
+
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Mock
+    private BluetoothRouteController.BluetoothRoutesUpdatedListener mListener;
+
+    @Mock
+    private BluetoothProfileMonitor mBluetoothProfileMonitor;
+
+    private AudioPoliciesBluetoothRouteController mAudioPoliciesBluetoothRouteController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        Application application = ApplicationProvider.getApplicationContext();
+        mContext = application;
+
+        BluetoothManager bluetoothManager = (BluetoothManager)
+                mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+
+        BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
+        mShadowBluetoothAdapter = Shadows.shadowOf(bluetoothAdapter);
+
+        mAudioPoliciesBluetoothRouteController =
+                new AudioPoliciesBluetoothRouteController(mContext, bluetoothAdapter,
+                        mBluetoothProfileMonitor, mListener) {
+                    @Override
+                    boolean isDeviceConnected(BluetoothDevice device) {
+                        return true;
+                    }
+                };
+
+        // Enable A2DP profile.
+        when(mBluetoothProfileMonitor.isProfileSupported(eq(BluetoothProfile.A2DP), any()))
+                .thenReturn(true);
+        mShadowBluetoothAdapter.setProfileConnectionState(BluetoothProfile.A2DP,
+                BluetoothProfile.STATE_CONNECTED);
+
+        mAudioPoliciesBluetoothRouteController.start(UserHandle.of(0));
+    }
+
+    @Test
+    public void getSelectedRoute_noBluetoothRoutesAvailable_returnsNull() {
+        assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+    }
+
+    @Test
+    public void selectRoute_noBluetoothRoutesAvailable_returnsFalse() {
+        assertThat(mAudioPoliciesBluetoothRouteController
+                .selectRoute(DEVICE_ADDRESS_UNKNOWN)).isFalse();
+    }
+
+    @Test
+    public void selectRoute_noDeviceWithGivenAddress_returnsFalse() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_3);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        assertThat(mAudioPoliciesBluetoothRouteController
+                .selectRoute(DEVICE_ADDRESS_SAMPLE_2)).isFalse();
+    }
+
+    @Test
+    public void selectRoute_deviceIsInDevicesSet_returnsTrue() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        assertThat(mAudioPoliciesBluetoothRouteController
+                .selectRoute(DEVICE_ADDRESS_SAMPLE_1)).isTrue();
+    }
+
+    @Test
+    public void selectRoute_resetSelectedDevice_returnsTrue() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_1);
+        assertThat(mAudioPoliciesBluetoothRouteController.selectRoute(null)).isTrue();
+    }
+
+    @Test
+    public void selectRoute_noSelectedDevice_returnsTrue() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        assertThat(mAudioPoliciesBluetoothRouteController.selectRoute(null)).isTrue();
+    }
+
+    @Test
+    public void getSelectedRoute_updateRouteFailed_returnsNull() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+        mAudioPoliciesBluetoothRouteController
+                .selectRoute(DEVICE_ADDRESS_SAMPLE_3);
+
+        assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+    }
+
+    @Test
+    public void getSelectedRoute_updateRouteSuccessful_returnsUpdateDevice() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4);
+
+        assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute()).isNull();
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        assertThat(mAudioPoliciesBluetoothRouteController
+                .selectRoute(DEVICE_ADDRESS_SAMPLE_4)).isTrue();
+
+        MediaRoute2Info selectedRoute = mAudioPoliciesBluetoothRouteController.getSelectedRoute();
+        assertThat(selectedRoute.getAddress()).isEqualTo(DEVICE_ADDRESS_SAMPLE_4);
+    }
+
+    @Test
+    public void getSelectedRoute_resetSelectedRoute_returnsNull() {
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(
+                DEVICE_ADDRESS_SAMPLE_1, DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4);
+
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        // Device is not null now.
+        mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+        // Rest the device.
+        mAudioPoliciesBluetoothRouteController.selectRoute(null);
+
+        assertThat(mAudioPoliciesBluetoothRouteController.getSelectedRoute())
+                .isNull();
+    }
+
+    @Test
+    public void getTransferableRoutes_noSelectedRoute_returnsAllBluetoothDevices() {
+        String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+                DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        // Force route controller to update bluetooth devices list.
+        sendBluetoothDevicesChangedBroadcast();
+
+        Set<String> transferableDevices = extractAddressesListFrom(
+                mAudioPoliciesBluetoothRouteController.getTransferableRoutes());
+        assertThat(transferableDevices).containsExactlyElementsIn(addresses);
+    }
+
+    @Test
+    public void getTransferableRoutes_hasSelectedRoute_returnsRoutesWithoutSelectedDevice() {
+        String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+                DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        // Force route controller to update bluetooth devices list.
+        sendBluetoothDevicesChangedBroadcast();
+        mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+        Set<String> transferableDevices = extractAddressesListFrom(
+                mAudioPoliciesBluetoothRouteController.getTransferableRoutes());
+        assertThat(transferableDevices).containsExactly(DEVICE_ADDRESS_SAMPLE_1,
+                DEVICE_ADDRESS_SAMPLE_2);
+    }
+
+    @Test
+    public void getAllBluetoothRoutes_hasSelectedRoute_returnsAllRoutes() {
+        String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+                DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        // Force route controller to update bluetooth devices list.
+        sendBluetoothDevicesChangedBroadcast();
+        mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+        Set<String> bluetoothDevices = extractAddressesListFrom(
+                mAudioPoliciesBluetoothRouteController.getAllBluetoothRoutes());
+        assertThat(bluetoothDevices).containsExactlyElementsIn(addresses);
+    }
+
+    @Test
+    public void updateVolumeForDevice_setVolumeForA2DPTo25_selectedRouteVolumeIsUpdated() {
+        String[] addresses = new String[] { DEVICE_ADDRESS_SAMPLE_1,
+                DEVICE_ADDRESS_SAMPLE_2, DEVICE_ADDRESS_SAMPLE_4 };
+        Set<BluetoothDevice> devices = generateFakeBluetoothDevicesSet(addresses);
+        mShadowBluetoothAdapter.setBondedDevices(devices);
+
+        // Force route controller to update bluetooth devices list.
+        sendBluetoothDevicesChangedBroadcast();
+        mAudioPoliciesBluetoothRouteController.selectRoute(DEVICE_ADDRESS_SAMPLE_4);
+
+        mAudioPoliciesBluetoothRouteController.updateVolumeForDevices(
+                AudioManager.DEVICE_OUT_BLUETOOTH_A2DP, 25);
+
+        MediaRoute2Info selectedRoute = mAudioPoliciesBluetoothRouteController.getSelectedRoute();
+        assertThat(selectedRoute.getVolume()).isEqualTo(25);
+    }
+
+    private void sendBluetoothDevicesChangedBroadcast() {
+        Intent intent = new Intent(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED);
+        mContext.sendBroadcast(intent);
+    }
+
+    private static Set<String> extractAddressesListFrom(Collection<MediaRoute2Info> routes) {
+        Set<String> addresses = new HashSet<>();
+
+        for (MediaRoute2Info route: routes) {
+            addresses.add(route.getAddress());
+        }
+
+        return addresses;
+    }
+
+    private static Set<BluetoothDevice> generateFakeBluetoothDevicesSet(String... addresses) {
+        Set<BluetoothDevice> devices = new HashSet<>();
+
+        for (String address: addresses) {
+            devices.add(ShadowBluetoothDevice.newInstance(address));
+        }
+
+        return devices;
+    }
+}
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 05a8b11..07ddda3 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -52,6 +52,10 @@
         "android.test.runner",
     ],
 
+    data: [
+        ":SimpleTestIme",
+    ],
+
     certificate: "platform",
     platform_apis: true,
     test_suites: ["device-tests"],
diff --git a/services/tests/InputMethodSystemServerTests/AndroidTest.xml b/services/tests/InputMethodSystemServerTests/AndroidTest.xml
index 92be780..1371934 100644
--- a/services/tests/InputMethodSystemServerTests/AndroidTest.xml
+++ b/services/tests/InputMethodSystemServerTests/AndroidTest.xml
@@ -21,6 +21,7 @@
         <option name="cleanup-apks" value="true" />
         <option name="install-arg" value="-t" />
         <option name="test-file-name" value="FrameworksInputMethodSystemServerTests.apk" />
+        <option name="test-file-name" value="SimpleTestIme.apk" />
     </target_preparer>
 
     <option name="test-tag" value="FrameworksInputMethodSystemServerTests" />
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.java
new file mode 100644
index 0000000..7cbfc52
--- /dev/null
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceRestrictImeAmountTest.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.server.inputmethod;
+
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.util.ArrayMap;
+import android.view.inputmethod.InputMethod;
+import android.view.inputmethod.InputMethodInfo;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class InputMethodManagerServiceRestrictImeAmountTest extends
+        InputMethodManagerServiceTestBase {
+
+    @Test
+    public void testFilterInputMethodServices_loadsAllImesBelowThreshold() {
+        List<ResolveInfo> resolveInfoList = new ArrayList<>();
+        for (int i = 0; i < 5; i++) {
+            resolveInfoList.add(
+                    createFakeResolveInfo("com.android.apps.inputmethod.simpleime", "IME" + i));
+        }
+
+        final List<InputMethodInfo> methodList = filterInputMethodServices(resolveInfoList,
+                List.of());
+        assertEquals(5, methodList.size());
+    }
+
+    @Test
+    public void testFilterInputMethodServices_ignoresImesBeyondThreshold() {
+        List<ResolveInfo> resolveInfoList = new ArrayList<>();
+        for (int i = 0; i < 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE; i++) {
+            resolveInfoList.add(
+                    createFakeResolveInfo("com.android.apps.inputmethod.simpleime", "IME" + i));
+        }
+
+        final List<InputMethodInfo> methodList = filterInputMethodServices(resolveInfoList,
+                List.of());
+        assertWithMessage("Filtered IMEs").that(methodList.size()).isEqualTo(
+                InputMethodInfo.MAX_IMES_PER_PACKAGE);
+    }
+
+    @Test
+    public void testFilterInputMethodServices_loadsSystemImesBeyondThreshold() {
+        List<ResolveInfo> resolveInfoList = new ArrayList<>();
+        for (int i = 0; i < 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE; i++) {
+            resolveInfoList.add(
+                    createFakeSystemResolveInfo("com.android.apps.inputmethod.systemime",
+                            "SystemIME" + i));
+        }
+
+        final List<InputMethodInfo> methodList = filterInputMethodServices(resolveInfoList,
+                List.of());
+        assertWithMessage("Filtered IMEs").that(methodList.size()).isEqualTo(
+                2 * InputMethodInfo.MAX_IMES_PER_PACKAGE);
+    }
+
+    @Test
+    public void testFilterInputMethodServices_ignoresImesBeyondThresholdFromTwoPackages() {
+        List<ResolveInfo> resolveInfoList = new ArrayList<>();
+        for (int i = 0; i < 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE; i++) {
+            resolveInfoList.add(
+                    createFakeResolveInfo("com.android.apps.inputmethod.simpleime1", "IME1_" + i));
+        }
+        for (int i = 0; i < 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE; i++) {
+            resolveInfoList.add(
+                    createFakeResolveInfo("com.android.apps.inputmethod.simpleime2", "IME2_" + i));
+        }
+
+        final List<InputMethodInfo> methodList = filterInputMethodServices(resolveInfoList,
+                List.of());
+        assertWithMessage("Filtered IMEs").that(methodList.size()).isEqualTo(
+                2 * InputMethodInfo.MAX_IMES_PER_PACKAGE);
+    }
+
+    @Test
+    public void testFilterInputMethodServices_stillLoadsEnabledImesBeyondThreshold() {
+        final ResolveInfo enabledIme = createFakeResolveInfo(
+                "com.android.apps.inputmethod.simpleime_enabled", "EnabledIME");
+
+        List<ResolveInfo> resolveInfoList = new ArrayList<>();
+        for (int i = 0; i < 2 * InputMethodInfo.MAX_IMES_PER_PACKAGE; i++) {
+            resolveInfoList.add(
+                    createFakeResolveInfo("com.android.apps.inputmethod.simpleime", "IME" + i));
+        }
+        resolveInfoList.add(enabledIme);
+
+        final List<InputMethodInfo> methodList = filterInputMethodServices(resolveInfoList,
+                List.of(new ComponentName(enabledIme.serviceInfo.packageName,
+                        enabledIme.serviceInfo.name).flattenToShortString()));
+
+        assertWithMessage("Filtered IMEs").that(methodList.size()).isEqualTo(
+                1 + InputMethodInfo.MAX_IMES_PER_PACKAGE);
+    }
+
+    private List<InputMethodInfo> filterInputMethodServices(List<ResolveInfo> resolveInfoList,
+            List<String> enabledComponents) {
+        final ArrayMap<String, InputMethodInfo> methodMap = new ArrayMap<>();
+        final ArrayList<InputMethodInfo> methodList = new ArrayList<>();
+        InputMethodManagerService.filterInputMethodServices(new ArrayMap<>(), methodMap, methodList,
+                enabledComponents, mContext, resolveInfoList);
+        return methodList;
+    }
+
+    private ResolveInfo createFakeSystemResolveInfo(String packageName, String componentName) {
+        final ResolveInfo ime = createFakeResolveInfo(packageName, componentName);
+        ime.serviceInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
+        return ime;
+    }
+
+    private ResolveInfo createFakeResolveInfo(String packageName, String componentName) {
+        final ResolveInfo ime = getResolveInfo("com.android.apps.inputmethod.simpleime");
+        if (packageName != null) {
+            ime.serviceInfo.packageName = packageName;
+        }
+        if (componentName != null) {
+            ime.serviceInfo.name = componentName;
+        }
+        return ime;
+    }
+
+    private ResolveInfo getResolveInfo(String packageName) {
+        final int flags = PackageManager.GET_META_DATA
+                | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
+        final List<ResolveInfo> ime = mContext.getPackageManager().queryIntentServices(
+                new Intent(InputMethod.SERVICE_INTERFACE).setPackage(packageName),
+                PackageManager.ResolveInfoFlags.of(flags));
+        assertWithMessage("Loaded IMEs").that(ime.size()).isGreaterThan(0);
+        return ime.get(0);
+    }
+}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index dbdffd0..9501b96 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -127,7 +127,7 @@
                 mockitoSession()
                         .initMocks(this)
                         .strictness(Strictness.LENIENT)
-                        .mockStatic(LocalServices.class)
+                        .spyStatic(LocalServices.class)
                         .mockStatic(ServiceManager.class)
                         .mockStatic(SystemServerInitThreadPool.class)
                         .startMocking();
@@ -212,6 +212,7 @@
                 new InputMethodManagerService.Lifecycle(mContext, mInputMethodManagerService);
 
         // Public local InputMethodManagerService.
+        LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
         lifecycle.onStart();
         try {
             // After this boot phase, services can broadcast Intents.
@@ -237,6 +238,7 @@
         if (mMockingSession != null) {
             mMockingSession.finishMocking();
         }
+        LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
     }
 
     protected void verifyShowSoftInput(boolean setVisible, boolean showSoftInput)
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/SwitchKeyboardLayoutTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/SwitchKeyboardLayoutTest.java
new file mode 100644
index 0000000..111cabd
--- /dev/null
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/SwitchKeyboardLayoutTest.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.server.inputmethod;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class SwitchKeyboardLayoutTest extends InputMethodManagerServiceTestBase {
+    @Test
+    public void testSwitchToNextKeyboardLayout() {
+        ExtendedMockito.spyOn(mInputMethodManagerService.mSwitchingController);
+        InputMethodManagerInternal.get().switchKeyboardLayout(1);
+        verify(mInputMethodManagerService.mSwitchingController)
+                .getNextInputMethodLocked(eq(true) /* onlyCurrentIme */, any(), any());
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 95c2ed2..99da415 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -759,40 +759,6 @@
     }
 
     /**
-     * Verify that sending a broadcast that removes any matching pending
-     * broadcasts is applied as expected.
-     */
-    @Test
-    public void testRemoveMatchingFilter() {
-        final Intent screenOn = new Intent(Intent.ACTION_SCREEN_ON);
-        final BroadcastOptions optionsOn = BroadcastOptions.makeBasic();
-        optionsOn.setRemoveMatchingFilter(new IntentFilter(Intent.ACTION_SCREEN_OFF));
-
-        final Intent screenOff = new Intent(Intent.ACTION_SCREEN_OFF);
-        final BroadcastOptions optionsOff = BroadcastOptions.makeBasic();
-        optionsOff.setRemoveMatchingFilter(new IntentFilter(Intent.ACTION_SCREEN_ON));
-
-        // Halt all processing so that we get a consistent view
-        mHandlerThread.getLooper().getQueue().postSyncBarrier();
-
-        mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, optionsOn));
-        mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, optionsOff));
-        mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOn, optionsOn));
-        mImpl.enqueueBroadcastLocked(makeBroadcastRecord(screenOff, optionsOff));
-
-        // While we're here, give our health check some test coverage
-        mImpl.checkHealthLocked();
-
-        // Marching through the queue we should only have one SCREEN_OFF
-        // broadcast, since that's the last state we dispatched
-        final BroadcastProcessQueue queue = mImpl.getProcessQueue(PACKAGE_GREEN,
-                getUidForPackage(PACKAGE_GREEN));
-        queue.makeActiveNextPending();
-        assertEquals(Intent.ACTION_SCREEN_OFF, queue.getActive().intent.getAction());
-        assertTrue(queue.isEmpty());
-    }
-
-    /**
      * Verify that sending a broadcast with DELIVERY_GROUP_POLICY_MOST_RECENT works as expected.
      */
     @Test
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 96b6345..3e0e5a8 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -64,6 +64,7 @@
 import com.android.server.display.RampAnimator.DualRampAnimator;
 import com.android.server.display.brightness.BrightnessEvent;
 import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.layout.Layout;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.testutils.OffsettableClock;
@@ -240,12 +241,15 @@
             boolean isEnabled) {
         DisplayInfo info = new DisplayInfo();
         DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
+        deviceInfo.uniqueId = uniqueId;
 
         when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
         when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
         when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
         when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
         when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
+        when(logicalDisplayMock.getBrightnessThrottlingDataIdLocked()).thenReturn(
+                DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID);
         when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
         when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
         when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
@@ -626,6 +630,19 @@
                 .setLightSensorEnabled(false);
     }
 
+    @Test
+    public void testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges() {
+        setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+                mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+
+        mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        verify(mHolder.screenOffBrightnessSensorController).stop();
+    }
+
     private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
             String uniqueId) {
         return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
@@ -662,8 +679,8 @@
                 mBrightnessTrackerMock, brightnessSetting, () -> {},
                 hbmMetadata, /* bootCompleted= */ false);
 
-        return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
-                automaticBrightnessController, wakelockController,
+        return new DisplayPowerControllerHolder(dpc, display, displayPowerState, brightnessSetting,
+                animator, automaticBrightnessController, wakelockController,
                 screenOffBrightnessSensorController, hbmMetadata);
     }
 
@@ -673,6 +690,7 @@
      */
     private static class DisplayPowerControllerHolder {
         public final DisplayPowerController2 dpc;
+        public final LogicalDisplay display;
         public final DisplayPowerState displayPowerState;
         public final BrightnessSetting brightnessSetting;
         public final DualRampAnimator<DisplayPowerState> animator;
@@ -681,7 +699,7 @@
         public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
         public final HighBrightnessModeMetadata hbmMetadata;
 
-        DisplayPowerControllerHolder(DisplayPowerController2 dpc,
+        DisplayPowerControllerHolder(DisplayPowerController2 dpc, LogicalDisplay display,
                 DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
                 DualRampAnimator<DisplayPowerState> animator,
                 AutomaticBrightnessController automaticBrightnessController,
@@ -689,6 +707,7 @@
                 ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
                 HighBrightnessModeMetadata hbmMetadata) {
             this.dpc = dpc;
+            this.display = display;
             this.displayPowerState = displayPowerState;
             this.brightnessSetting = brightnessSetting;
             this.animator = animator;
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 28319ac..6c4afd3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -64,6 +64,7 @@
 import com.android.server.display.RampAnimator.DualRampAnimator;
 import com.android.server.display.brightness.BrightnessEvent;
 import com.android.server.display.color.ColorDisplayService;
+import com.android.server.display.layout.Layout;
 import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
 import com.android.server.policy.WindowManagerPolicy;
 import com.android.server.testutils.OffsettableClock;
@@ -243,12 +244,15 @@
             boolean isEnabled) {
         DisplayInfo info = new DisplayInfo();
         DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
+        deviceInfo.uniqueId = uniqueId;
 
         when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
         when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
         when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
         when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
         when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
+        when(logicalDisplayMock.getBrightnessThrottlingDataIdLocked()).thenReturn(
+                DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID);
         when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
         when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
         when(displayDeviceMock.getDisplayDeviceConfig()).thenReturn(displayDeviceConfigMock);
@@ -630,6 +634,19 @@
                 .setLightSensorEnabled(false);
     }
 
+    @Test
+    public void testStopScreenOffBrightnessSensorControllerWhenDisplayDeviceChanges() {
+        setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
+                mock(DisplayDeviceConfig.class), /* isEnabled= */ true);
+
+        mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY);
+        DisplayPowerRequest dpr = new DisplayPowerRequest();
+        mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+        advanceTime(1); // Run updatePowerState
+
+        verify(mHolder.screenOffBrightnessSensorController).stop();
+    }
+
     private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
             String uniqueId) {
         return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
@@ -665,8 +682,9 @@
                 mBrightnessTrackerMock, brightnessSetting, () -> {},
                 hbmMetadata, /* bootCompleted= */ false);
 
-        return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
-                automaticBrightnessController, screenOffBrightnessSensorController, hbmMetadata);
+        return new DisplayPowerControllerHolder(dpc, display, displayPowerState, brightnessSetting,
+                animator, automaticBrightnessController, screenOffBrightnessSensorController,
+                hbmMetadata);
     }
 
     /**
@@ -675,6 +693,7 @@
      */
     private static class DisplayPowerControllerHolder {
         public final DisplayPowerController dpc;
+        public final LogicalDisplay display;
         public final DisplayPowerState displayPowerState;
         public final BrightnessSetting brightnessSetting;
         public final DualRampAnimator<DisplayPowerState> animator;
@@ -682,13 +701,14 @@
         public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
         public final HighBrightnessModeMetadata hbmMetadata;
 
-        DisplayPowerControllerHolder(DisplayPowerController dpc,
+        DisplayPowerControllerHolder(DisplayPowerController dpc, LogicalDisplay display,
                 DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
                 DualRampAnimator<DisplayPowerState> animator,
                 AutomaticBrightnessController automaticBrightnessController,
                 ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
                 HighBrightnessModeMetadata hbmMetadata) {
             this.dpc = dpc;
+            this.display = display;
             this.displayPowerState = displayPowerState;
             this.brightnessSetting = brightnessSetting;
             this.animator = animator;
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 95a5884..5f82ec1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -53,6 +53,7 @@
 import com.android.internal.R;
 import com.android.server.LocalServices;
 import com.android.server.display.LocalDisplayAdapter.BacklightAdapter;
+import com.android.server.display.mode.DisplayModeDirector;
 import com.android.server.lights.LightsManager;
 import com.android.server.lights.LogicalLight;
 
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 991d566..8b420a3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -234,15 +234,9 @@
                 createJobInfo(5).setPriority(JobInfo.PRIORITY_HIGH));
         JobStatus jobDef = createJobStatus("testGetMinJobExecutionGuaranteeMs",
                 createJobInfo(6));
-        JobStatus jobDT = createJobStatus("testGetMinJobExecutionGuaranteeMs",
-                createJobInfo(7)
-                        .setDataTransfer(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
-        JobStatus jobUI = createJobStatus("testGetMinJobExecutionGuaranteeMs",
-                createJobInfo(8)); // TODO(255371817): add setUserInitiated(true)
         JobStatus jobUIDT = createJobStatus("testGetMinJobExecutionGuaranteeMs",
-                // TODO(255371817): add setUserInitiated(true)
                 createJobInfo(9)
-                        .setDataTransfer(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
+                        .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
 
         spyOn(ejMax);
         spyOn(ejHigh);
@@ -250,8 +244,6 @@
         spyOn(ejHighDowngraded);
         spyOn(jobHigh);
         spyOn(jobDef);
-        spyOn(jobDT);
-        spyOn(jobUI);
         spyOn(jobUIDT);
 
         when(ejMax.shouldTreatAsExpeditedJob()).thenReturn(true);
@@ -260,14 +252,11 @@
         when(ejHighDowngraded.shouldTreatAsExpeditedJob()).thenReturn(false);
         when(jobHigh.shouldTreatAsExpeditedJob()).thenReturn(false);
         when(jobDef.shouldTreatAsExpeditedJob()).thenReturn(false);
-        when(jobUI.shouldTreatAsUserInitiatedJob()).thenReturn(true);
         when(jobUIDT.shouldTreatAsUserInitiatedJob()).thenReturn(true);
 
         ConnectivityController connectivityController = mService.getConnectivityController();
         spyOn(connectivityController);
         mService.mConstants.RUNTIME_MIN_GUARANTEE_MS = 10 * MINUTE_IN_MILLIS;
-        mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS = 15 * MINUTE_IN_MILLIS;
-        mService.mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS = 60 * MINUTE_IN_MILLIS;
         mService.mConstants.RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR = 1.5f;
         mService.mConstants.RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS = HOUR_IN_MILLIS;
         mService.mConstants.RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS = 6 * HOUR_IN_MILLIS;
@@ -284,37 +273,14 @@
                 mService.getMinJobExecutionGuaranteeMs(jobHigh));
         assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
                 mService.getMinJobExecutionGuaranteeMs(jobDef));
-        grantRunUserInitiatedJobsPermission(false); // Without permission
-        assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
-                mService.getMinJobExecutionGuaranteeMs(jobDT));
-        grantRunUserInitiatedJobsPermission(true); // With permission
-        doReturn(ConnectivityController.UNKNOWN_TIME)
-                .when(connectivityController).getEstimatedTransferTimeMs(any());
-        assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
-                mService.getMinJobExecutionGuaranteeMs(jobDT));
-        doReturn(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS / 2)
-                .when(connectivityController).getEstimatedTransferTimeMs(any());
-        assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
-                mService.getMinJobExecutionGuaranteeMs(jobDT));
-        doReturn(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS * 2)
-                .when(connectivityController).getEstimatedTransferTimeMs(any());
-        assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
-                mService.getMinJobExecutionGuaranteeMs(jobDT));
-        doReturn(mService.mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS * 2)
-                .when(connectivityController).getEstimatedTransferTimeMs(any());
-        assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
-                mService.getMinJobExecutionGuaranteeMs(jobDT));
         // UserInitiated
         grantRunUserInitiatedJobsPermission(false);
-        // Permission isn't granted, so it should just be treated as a regular data transfer job.
-        assertEquals(mService.mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
-                mService.getMinJobExecutionGuaranteeMs(jobUIDT));
         // Permission isn't granted, so it should just be treated as a regular job.
         assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
-                mService.getMinJobExecutionGuaranteeMs(jobUI));
+                mService.getMinJobExecutionGuaranteeMs(jobUIDT));
         grantRunUserInitiatedJobsPermission(true); // With permission
-        assertEquals(mService.mConstants.RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
-                mService.getMinJobExecutionGuaranteeMs(jobUI));
+        assertEquals(mService.mConstants.RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS,
+                mService.getMinJobExecutionGuaranteeMs(jobUIDT));
         doReturn(ConnectivityController.UNKNOWN_TIME)
                 .when(connectivityController).getEstimatedTransferTimeMs(any());
         assertEquals(mService.mConstants.RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS,
@@ -338,21 +304,10 @@
 
     @Test
     public void testGetMaxJobExecutionTimeMs() {
-        JobStatus jobDT = createJobStatus("testGetMaxJobExecutionTimeMs",
-                createJobInfo(7)
-                        .setDataTransfer(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
-        JobStatus jobUI = createJobStatus("testGetMaxJobExecutionTimeMs",
-                createJobInfo(9)); // TODO(255371817): add setUserInitiated(true)
         JobStatus jobUIDT = createJobStatus("testGetMaxJobExecutionTimeMs",
-                // TODO(255371817): add setUserInitiated(true)
                 createJobInfo(10)
-                        .setDataTransfer(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
-
-        spyOn(jobDT);
-        spyOn(jobUI);
+                        .setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
         spyOn(jobUIDT);
-
-        when(jobUI.shouldTreatAsUserInitiatedJob()).thenReturn(true);
         when(jobUIDT.shouldTreatAsUserInitiatedJob()).thenReturn(true);
 
         QuotaController quotaController = mService.getQuotaController();
@@ -365,17 +320,9 @@
                 .when(quotaController).getMaxJobExecutionTimeMsLocked(any());
 
         grantRunUserInitiatedJobsPermission(true);
-        assertEquals(mService.mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS,
-                mService.getMaxJobExecutionTimeMs(jobDT));
-        assertEquals(mService.mConstants.RUNTIME_USER_INITIATED_LIMIT_MS,
-                mService.getMaxJobExecutionTimeMs(jobUI));
         assertEquals(mService.mConstants.RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUIDT));
         grantRunUserInitiatedJobsPermission(false);
-        assertEquals(mService.mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS,
-                mService.getMaxJobExecutionTimeMs(jobDT));
-        assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
-                mService.getMaxJobExecutionTimeMs(jobUI));
         assertEquals(mService.mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                 mService.getMaxJobExecutionTimeMs(jobUIDT));
     }
@@ -478,7 +425,8 @@
     @Test
     public void testGetRescheduleJobForFailure_userStopped() {
         JobStatus uiJob = createJobStatus("testGetRescheduleJobForFailure",
-                createJobInfo().setUserInitiated(true));
+                createJobInfo().setUserInitiated(true)
+                        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY));
         JobStatus uvJob = createJobStatus("testGetRescheduleJobForFailure", createJobInfo());
         spyOn(uvJob);
         doReturn(true).when(uvJob).isUserVisibleJob();
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
index 1e65b38..6bc552c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
@@ -619,7 +619,7 @@
     @Test
     public void testExceptions_UserInitiated() {
         JobInfo.Builder jb = createJob(0);
-        jb.setUserInitiated(true);
+        jb.setUserInitiated(true).setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
         JobStatus js = createJobStatus("testExceptions_UserInitiated", jb);
         assertFalse(js.hasFlexibilityConstraint());
     }
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 e6bc72f..5dc8ed5 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
@@ -170,6 +170,7 @@
         final JobInfo jobInfo =
                 new JobInfo.Builder(101, new ComponentName("foo", "bar"))
                         .setUserInitiated(true)
+                        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                         .build();
         JobStatus job = createJobStatus(jobInfo);
         assertTrue(job.canRunInBatterySaver());
@@ -216,6 +217,7 @@
         final JobInfo jobInfo =
                 new JobInfo.Builder(101, new ComponentName("foo", "bar"))
                         .setUserInitiated(true)
+                        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                         .build();
         JobStatus job = createJobStatus(jobInfo);
         assertTrue(job.canRunInDoze());
@@ -236,6 +238,7 @@
         // User-initiated jobs are always user-visible unless they've been demoted.
         jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
                 .setUserInitiated(true)
+                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                 .build();
         job = createJobStatus(jobInfo);
 
@@ -507,6 +510,7 @@
 
         jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
                 .setUserInitiated(true)
+                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                 .build();
         job = createJobStatus(jobInfo);
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 3f5d113..06ba5dd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -664,7 +664,7 @@
     private fun mockQueryActivities(action: String, vararg activities: ActivityInfo) {
         whenever(mocks.componentResolver.queryActivities(any(),
                 argThat { intent: Intent? -> intent != null && (action == intent.action) },
-                nullable(), anyLong(), anyInt(), anyInt())) {
+                nullable(), anyLong(), anyInt())) {
             ArrayList(activities.asList().map { info: ActivityInfo? ->
                 ResolveInfo().apply { activityInfo = info }
             })
@@ -674,7 +674,7 @@
     private fun mockQueryServices(action: String, vararg services: ServiceInfo) {
         whenever(mocks.componentResolver.queryServices(any(),
                 argThat { intent: Intent? -> intent != null && (action == intent.action) },
-                nullable(), anyLong(), anyInt(), anyInt())) {
+                nullable(), anyLong(), anyInt())) {
             ArrayList(services.asList().map { info ->
                 ResolveInfo().apply { serviceInfo = info }
             })
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 503e579..96eca71 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -289,7 +289,7 @@
 
     @SmallTest
     @Test
-    public void testRegisterProxyWithoutPermission() throws Exception {
+    public void testRegisterProxyWithoutA11yPermission() throws Exception {
         doThrow(SecurityException.class).when(mMockSecurityPolicy)
                 .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
 
@@ -301,6 +301,18 @@
 
     @SmallTest
     @Test
+    public void testRegisterProxyWithoutDevicePermission() throws Exception {
+        doThrow(SecurityException.class).when(mMockSecurityPolicy)
+                .enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
+
+        assertThrows(SecurityException.class,
+                () -> mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY));
+        verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+                any(), any(), any());
+    }
+
+    @SmallTest
+    @Test
     public void testRegisterProxyForDefaultDisplay() throws Exception {
         assertThrows(IllegalArgumentException.class,
                 () -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.DEFAULT_DISPLAY));
@@ -328,7 +340,7 @@
 
     @SmallTest
     @Test
-    public void testUnRegisterProxyWithoutPermission() throws Exception {
+    public void testUnRegisterProxyWithoutA11yPermission() {
         doThrow(SecurityException.class).when(mMockSecurityPolicy)
                 .enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ACCESSIBILITY);
 
@@ -339,6 +351,17 @@
 
     @SmallTest
     @Test
+    public void testUnRegisterProxyWithoutDevicePermission() {
+        doThrow(SecurityException.class).when(mMockSecurityPolicy)
+                .enforceCallingOrSelfPermission(Manifest.permission.CREATE_VIRTUAL_DEVICE);
+
+        assertThrows(SecurityException.class,
+                () -> mA11yms.unregisterProxyForDisplay(TEST_DISPLAY));
+        verify(mProxyManager, never()).unregisterProxy(TEST_DISPLAY);
+    }
+
+    @SmallTest
+    @Test
     public void testOnMagnificationTransitionFailed_capabilitiesIsAll_fallBackToPreviousMode() {
         final AccessibilityUserState userState = mA11yms.mUserStates.get(
                 mA11yms.getCurrentUserIdLocked());
diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
index 1298e7b..24b003c 100644
--- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.nullable;
 import static org.mockito.Mockito.times;
@@ -37,6 +38,7 @@
 import android.accounts.CantAddAccountActivity;
 import android.accounts.IAccountManagerResponse;
 import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
 import android.app.INotificationManager;
 import android.app.PropertyInvalidatedCache;
 import android.app.admin.DevicePolicyManager;
@@ -171,6 +173,16 @@
         setContext(mockContext);
         mTestInjector = new TestInjector(realTestContext, mockContext, mMockNotificationManager);
         mAms = new AccountManagerService(mTestInjector);
+        doAnswer(invocation -> {
+            final Intent intent = invocation.getArgument(0);
+            final Bundle options = invocation.getArgument(3);
+            if (AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION.endsWith(intent.getAction())) {
+                final BroadcastOptions bOptions = new BroadcastOptions(options);
+                assertEquals(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT,
+                        bOptions.getDeliveryGroupPolicy());
+            }
+            return null;
+        }).when(mMockContext).sendBroadcastAsUser(any(), any(), any(), any());
     }
 
     @Override
@@ -3142,7 +3154,7 @@
         mAccountRemovedBroadcasts = 0;
         ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
         verify(mMockContext, atLeast(expectedBroadcasts)).sendBroadcastAsUser(captor.capture(),
-            any(UserHandle.class));
+                any(UserHandle.class), any(), any());
         for (Intent intent : captor.getAllValues()) {
             if (AccountManager.ACTION_VISIBLE_ACCOUNTS_CHANGED.equals(intent.getAction())) {
                 mVisibleAccountsChangedBroadcasts++;
@@ -3499,7 +3511,19 @@
 
         @Override
         public void sendBroadcastAsUser(Intent intent, UserHandle user) {
-            mMockContext.sendBroadcastAsUser(intent, user);
+            sendBroadcastAsUser(intent, user, null, null);
+        }
+
+        @Override
+        public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission,
+                Bundle options) {
+            mMockContext.sendBroadcastAsUser(intent, user, receiverPermission, options);
+        }
+
+        @Override
+        public Intent registerReceiver(BroadcastReceiver receiver,
+                IntentFilter filter, String broadcastPermission, Handler scheduler) {
+            return mMockContext.registerReceiver(receiver, filter, broadcastPermission, scheduler);
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
index 4412cfe..8cbed2c 100644
--- a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
@@ -305,60 +305,4 @@
         assertEquals("Interaction event time was not updated correctly.",
                 interactionEventTime, mProcessRecord.mState.getInteractionEventTime());
     }
-
-    private void updateShortFgsOwner(int uid, int pid, boolean add) {
-        sService.mOomAdjuster.updateShortFgsOwner(uid, pid, add);
-    }
-
-    private void assertHasUidShortForegroundService(int uid, boolean expected) {
-        assertEquals(expected, sService.mOomAdjuster.hasUidShortForegroundService(uid));
-    }
-
-    @Test
-    public void testHasUidShortForegroundService() {
-        assertHasUidShortForegroundService(1, false);
-        assertHasUidShortForegroundService(2, false);
-        assertHasUidShortForegroundService(3, false);
-        assertHasUidShortForegroundService(100, false);
-        assertHasUidShortForegroundService(101, false);
-
-        updateShortFgsOwner(1, 100, true);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(100, false);
-        assertHasUidShortForegroundService(2, false);
-
-        updateShortFgsOwner(1, 101, true);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(101, false);
-        assertHasUidShortForegroundService(2, false);
-
-        updateShortFgsOwner(2, 200, true);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, true);
-        assertHasUidShortForegroundService(200, false);
-
-        updateShortFgsOwner(1, 101, false);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, true);
-
-        updateShortFgsOwner(1, 99, false); // unused PID
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, true);
-
-        updateShortFgsOwner(1, 100, false);
-        assertHasUidShortForegroundService(1, false);
-        assertHasUidShortForegroundService(2, true);
-
-        updateShortFgsOwner(1, 100, true);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, true);
-
-        updateShortFgsOwner(2, 200, false);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, false);
-
-        updateShortFgsOwner(2, 201, true);
-        assertHasUidShortForegroundService(1, true);
-        assertHasUidShortForegroundService(2, true);
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index cf650d2..e9d8269 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -40,7 +40,9 @@
 import android.hardware.biometrics.AuthenticateOptions;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
+import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.biometrics.IBiometricService;
+import android.hardware.fingerprint.Fingerprint;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -49,6 +51,7 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableContext;
 import android.testing.TestableLooper;
+import android.util.Slog;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -59,6 +62,8 @@
 import com.android.server.biometrics.log.BiometricLogger;
 import com.android.server.biometrics.nano.BiometricSchedulerProto;
 import com.android.server.biometrics.nano.BiometricsProto;
+import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils;
+import com.android.server.biometrics.sensors.fingerprint.aidl.AidlSession;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -68,6 +73,9 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.function.Supplier;
 
 @Presubmit
@@ -79,6 +87,9 @@
     private static final String TAG = "BiometricSchedulerTest";
     private static final int TEST_SENSOR_ID = 1;
     private static final int LOG_NUM_RECENT_OPERATIONS = 2;
+    private static final Fingerprint TEST_FINGERPRINT = new Fingerprint("" /* name */,
+            1 /* fingerId */, TEST_SENSOR_ID);
+
     @Rule
     public final TestableContext mContext = new TestableContext(
             InstrumentationRegistry.getContext(), null);
@@ -674,6 +685,56 @@
 
     }
 
+    @Test
+    public void testTwoInternalCleanupOps_withFirstFavorHalEnrollment() throws Exception {
+        final String owner = "test.owner";
+        final int userId = 1;
+        final Supplier<Object> daemon = () -> mock(AidlSession.class);
+        final FingerprintUtils utils = mock(FingerprintUtils.class);
+        final Map<Integer, Long> authenticatorIds = new HashMap<>();
+        final ClientMonitorCallback callback0 = mock(ClientMonitorCallback.class);
+        final ClientMonitorCallback callback1 = mock(ClientMonitorCallback.class);
+        final ClientMonitorCallback callback2 = mock(ClientMonitorCallback.class);
+
+        final TestInternalCleanupClient client1 = new
+                TestInternalCleanupClient(mContext, daemon, userId,
+                owner, TEST_SENSOR_ID, mock(BiometricLogger.class),
+                mBiometricContext, utils, authenticatorIds);
+        final TestInternalCleanupClient client2 = new
+                TestInternalCleanupClient(mContext, daemon, userId,
+                owner, TEST_SENSOR_ID, mock(BiometricLogger.class),
+                mBiometricContext, utils, authenticatorIds);
+
+        //add initial start client to scheduler, so later clients will be on pending operation queue
+        final TestHalClientMonitor startClient = new TestHalClientMonitor(mContext, mToken,
+                daemon);
+        mScheduler.scheduleClientMonitor(startClient, callback0);
+
+        //add first cleanup client which favors enrollments from HAL
+        client1.setFavorHalEnrollments();
+        mScheduler.scheduleClientMonitor(client1, callback1);
+        assertEquals(1, mScheduler.mPendingOperations.size());
+
+        when(utils.getBiometricsForUser(mContext, userId)).thenAnswer(i ->
+                new ArrayList<>(client1.getFingerprints()));
+
+        //add second cleanup client
+        mScheduler.scheduleClientMonitor(client2, callback2);
+
+        //finish the start client, so other pending clients are processed
+        startClient.getCallback().onClientFinished(startClient, true);
+
+        waitForIdle();
+
+        assertTrue(client1.isAlreadyDone());
+        assertTrue(client2.isAlreadyDone());
+        assertNull(mScheduler.mCurrentOperation);
+        verify(utils, never()).removeBiometricForUser(mContext, userId,
+                TEST_FINGERPRINT.getBiometricId());
+        assertEquals(1,  client1.getFingerprints().size());
+    }
+
+
     private BiometricSchedulerProto getDump(boolean clearSchedulerBuffer) throws Exception {
         return BiometricSchedulerProto.parseFrom(mScheduler.dumpProtoState(clearSchedulerBuffer));
     }
@@ -867,4 +928,90 @@
             mDestroyed = true;
         }
     }
+
+    private static class TestInternalEnumerateClient extends InternalEnumerateClient<Object> {
+        private static final String TAG = "TestInternalEnumerateClient";
+
+
+        protected TestInternalEnumerateClient(@NonNull Context context,
+                @NonNull Supplier<Object> lazyDaemon, @NonNull IBinder token, int userId,
+                @NonNull String owner, @NonNull List<Fingerprint> enrolledList,
+                @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
+                @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
+            super(context, lazyDaemon, token, userId, owner, enrolledList, utils, sensorId,
+                    logger, biometricContext);
+        }
+
+        @Override
+        protected void startHalOperation() {
+            Slog.d(TAG, "TestInternalEnumerateClient#startHalOperation");
+            onEnumerationResult(TEST_FINGERPRINT, 0 /* remaining */);
+        }
+    }
+
+    private static class TestRemovalClient extends RemovalClient<Fingerprint, Object> {
+        private static final String TAG = "TestRemovalClient";
+
+        TestRemovalClient(@NonNull Context context,
+                @NonNull Supplier<Object> lazyDaemon, @NonNull IBinder token,
+                @Nullable ClientMonitorCallbackConverter listener, int[] biometricIds, int userId,
+                @NonNull String owner, @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
+                @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+                @NonNull Map<Integer, Long> authenticatorIds) {
+            super(context, lazyDaemon, token, listener, userId, owner, utils, sensorId,
+                    logger, biometricContext, authenticatorIds);
+        }
+
+        @Override
+        protected void startHalOperation() {
+            Slog.d(TAG, "Removing template from hw");
+            onRemoved(TEST_FINGERPRINT, 0);
+        }
+    }
+
+    private static class TestInternalCleanupClient extends
+            InternalCleanupClient<Fingerprint, Object> {
+        private List<Fingerprint> mFingerprints = new ArrayList<>();
+
+        TestInternalCleanupClient(@NonNull Context context,
+                @NonNull Supplier<Object> lazyDaemon,
+                int userId, @NonNull String owner, int sensorId,
+                @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+                @NonNull FingerprintUtils utils, @NonNull Map<Integer, Long> authenticatorIds) {
+            super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
+                    utils, authenticatorIds);
+        }
+
+        @Override
+        protected InternalEnumerateClient<Object> getEnumerateClient(Context context,
+                Supplier<Object> lazyDaemon, IBinder token, int userId, String owner,
+                List<Fingerprint> enrolledList, BiometricUtils<Fingerprint> utils, int sensorId,
+                @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
+            return new TestInternalEnumerateClient(context, lazyDaemon, token, userId, owner,
+                    enrolledList, utils, sensorId,
+                    logger.swapAction(context, BiometricsProtoEnums.ACTION_ENUMERATE),
+                    biometricContext);
+        }
+
+        @Override
+        protected RemovalClient<Fingerprint, Object> getRemovalClient(Context context,
+                Supplier<Object> lazyDaemon, IBinder token, int biometricId, int userId,
+                String owner, BiometricUtils<Fingerprint> utils, int sensorId,
+                @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+                Map<Integer, Long> authenticatorIds) {
+            return new TestRemovalClient(context, lazyDaemon, token, null,
+                    new int[]{biometricId}, userId, owner, utils, sensorId, logger,
+                    biometricContext, authenticatorIds);
+        }
+
+        @Override
+        protected void onAddUnknownTemplate(int userId,
+                @NonNull BiometricAuthenticator.Identifier identifier) {
+            mFingerprints.add((Fingerprint) identifier);
+        }
+
+        public List<Fingerprint> getFingerprints() {
+            return mFingerprints;
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
index f0d8616..5806443 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClientTest.java
@@ -164,10 +164,9 @@
     }
 
     protected FingerprintInternalCleanupClient createClient() {
-        final List<Fingerprint> enrollments = new ArrayList<>();
         final Map<Integer, Long> authenticatorIds = new HashMap<>();
         return new FingerprintInternalCleanupClient(mContext, () -> mAidlSession, 2 /* userId */,
-                "the.test.owner", SENSOR_ID, mLogger, mBiometricContext, enrollments,
+                "the.test.owner", SENSOR_ID, mLogger, mBiometricContext,
                 mFingerprintUtils, authenticatorIds) {
             @Override
             protected void onAddUnknownTemplate(int userId,
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
index 760ed9b..7642e7b 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
@@ -87,7 +87,7 @@
 
         // Allow virtual devices to be created on the looper thread for testing.
         final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true;
-        mInputController = new InputController(new Object(), mNativeWrapperMock,
+        mInputController = new InputController(mNativeWrapperMock,
                 new Handler(TestableLooper.get(this).getLooper()),
                 InstrumentationRegistry.getTargetContext().getSystemService(WindowManager.class),
                 threadVerifier);
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
index 6431e88..1259d71 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/SensorControllerTest.java
@@ -81,7 +81,7 @@
     @Test
     public void createSensor_invalidHandle_throwsException() {
         doReturn(/* handle= */0).when(mSensorManagerInternalMock).createRuntimeSensor(
-                anyInt(), anyInt(), anyString(), anyString(), any());
+                anyInt(), anyInt(), anyString(), anyString(), anyInt(), any());
 
         Throwable thrown = assertThrows(
                 RuntimeException.class,
@@ -138,7 +138,7 @@
 
     private void doCreateSensorSuccessfully() {
         doReturn(SENSOR_HANDLE).when(mSensorManagerInternalMock).createRuntimeSensor(
-                anyInt(), anyInt(), anyString(), anyString(), any());
+                anyInt(), anyInt(), anyString(), anyString(), anyInt(), any());
         assertThat(mSensorController.createSensor(mSensorToken, mVirtualSensorConfig))
                 .isEqualTo(SENSOR_HANDLE);
     }
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index cc6f7c2..09a84da 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -16,11 +16,11 @@
 
 package com.android.server.companion.virtual;
 
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_INVALID;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS;
+import static android.content.Context.DEVICE_ID_DEFAULT;
+import static android.content.Context.DEVICE_ID_INVALID;
 import static android.content.Intent.ACTION_VIEW;
 import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES;
 
@@ -355,7 +355,7 @@
                 TestableLooper.get(this), mNativeWrapperMock, mIInputManagerMock);
         // Allow virtual devices to be created on the looper thread for testing.
         final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true;
-        mInputController = new InputController(new Object(), mNativeWrapperMock,
+        mInputController = new InputController(mNativeWrapperMock,
                 new Handler(TestableLooper.get(this).getLooper()),
                 mContext.getSystemService(WindowManager.class), threadVerifier);
         mSensorController =
@@ -500,7 +500,7 @@
                 .build();
 
         doReturn(SENSOR_HANDLE).when(mSensorManagerInternalMock).createRuntimeSensor(
-                anyInt(), anyInt(), anyString(), anyString(), any());
+                anyInt(), anyInt(), anyString(), anyString(), anyInt(), any());
         mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
 
         VirtualSensor sensor = mLocalService.getVirtualSensor(VIRTUAL_DEVICE_ID_1, SENSOR_HANDLE);
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
index bb28a36..a2e204d 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
@@ -16,8 +16,8 @@
 
 package com.android.server.companion.virtual;
 
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_DEFAULT;
-import static android.companion.virtual.VirtualDeviceManager.DEVICE_ID_INVALID;
+import static android.content.Context.DEVICE_ID_DEFAULT;
+import static android.content.Context.DEVICE_ID_INVALID;
 
 import static com.google.common.truth.Truth.assertThat;
 
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
index 800f60b..ffe2fec 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
@@ -43,6 +43,7 @@
 import com.android.server.display.BrightnessThrottler.Injector;
 import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData;
 import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
+import com.android.server.display.mode.DisplayModeDirectorTest;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
index 6def7b1..8981160 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java
@@ -176,21 +176,18 @@
         assertFalse(mInjector.mColorSamplingEnabled);
 
         // Update brightness config to enabled color sampling.
-        mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
-                /* collectColorSamples= */ true));
+        mTracker.setShouldCollectColorSample(/* collectColorSamples= */ true);
         mInjector.waitForHandler();
         assertTrue(mInjector.mColorSamplingEnabled);
 
         // Update brightness config to disable color sampling.
-        mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
-                /* collectColorSamples= */ false));
+        mTracker.setShouldCollectColorSample(/* collectColorSamples= */ false);
         mInjector.waitForHandler();
         assertFalse(mInjector.mColorSamplingEnabled);
 
         // Pretend screen is off, update config to turn on color sampling.
         mInjector.sendScreenChange(/* screenOn= */ false);
-        mTracker.setBrightnessConfiguration(buildBrightnessConfiguration(
-                /* collectColorSamples= */ true));
+        mTracker.setShouldCollectColorSample(/* collectColorSamples= */ true);
         mInjector.waitForHandler();
         assertFalse(mInjector.mColorSamplingEnabled);
 
@@ -883,7 +880,7 @@
     private void startTracker(BrightnessTracker tracker, float initialBrightness,
             boolean collectColorSamples) {
         tracker.start(initialBrightness);
-        tracker.setBrightnessConfiguration(buildBrightnessConfiguration(collectColorSamples));
+        tracker.setShouldCollectColorSample(collectColorSamples);
         mInjector.waitForHandler();
     }
 
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 1b6b143..7971fd7 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -28,6 +28,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyLong;
@@ -127,6 +128,10 @@
 
     private Context mContext;
 
+    private int mHdrConversionMode;
+
+    private int mPreferredHdrOutputType;
+
     private final DisplayManagerService.Injector mShortMockedInjector =
             new DisplayManagerService.Injector() {
                 @Override
@@ -176,6 +181,8 @@
         @Override
         int setHdrConversionMode(int conversionMode, int preferredHdrOutputType,
                 int[] autoHdrTypes) {
+            mHdrConversionMode = conversionMode;
+            mPreferredHdrOutputType = preferredHdrOutputType;
             return Display.HdrCapabilities.HDR_TYPE_INVALID;
         }
 
@@ -185,7 +192,7 @@
         }
 
         boolean getHdrOutputConversionSupport() {
-            return false;
+            return true;
         }
    }
 
@@ -1541,6 +1548,40 @@
                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
     }
 
+    @Test
+    public void testCreateHdrConversionMode_withInvalidArguments_throwsException() {
+        assertThrows(
+                "preferredHdrOutputType must not be set if the conversion mode is "
+                        + "HDR_CONVERSION_PASSTHROUGH",
+                IllegalArgumentException.class,
+                () -> new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH,
+                        Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION));
+    }
+
+    @Test
+    public void testSetHdrConversionModeInternal_withInvalidArguments_throwsException() {
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+        assertThrows("Expected DisplayManager to throw IllegalArgumentException when "
+                        + "preferredHdrOutputType is set and the conversion mode is "
+                        + "HDR_CONVERSION_SYSTEM",
+                IllegalArgumentException.class,
+                () -> displayManager.setHdrConversionModeInternal(new HdrConversionMode(
+                        HdrConversionMode.HDR_CONVERSION_SYSTEM,
+                        Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION)));
+    }
+
+    @Test
+    public void testSetAndGetHdrConversionModeInternal() {
+        DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
+        final HdrConversionMode mode = new HdrConversionMode(
+                HdrConversionMode.HDR_CONVERSION_FORCE,
+                Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION);
+        displayManager.setHdrConversionModeInternal(mode);
+        assertEquals(mode, displayManager.getHdrConversionModeSettingInternal());
+        assertEquals(mode.getConversionMode(), mHdrConversionMode);
+        assertEquals(mode.getPreferredHdrOutputType(), mPreferredHdrOutputType);
+    }
+
     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/mode/DisplayModeDirectorTest.java
similarity index 99%
rename from services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
rename to services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index 7e6eeee..f256c8a 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.server.display;
+package com.android.server.display.mode;
 
 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA;
 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS;
@@ -27,8 +27,7 @@
 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE;
 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
 
-import static com.android.server.display.DisplayModeDirector.Vote.INVALID_SIZE;
-import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID;
+import static com.android.server.display.mode.DisplayModeDirector.Vote.INVALID_SIZE;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -88,9 +87,11 @@
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.internal.util.test.FakeSettingsProviderRule;
 import com.android.server.LocalServices;
-import com.android.server.display.DisplayModeDirector.BrightnessObserver;
-import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
-import com.android.server.display.DisplayModeDirector.Vote;
+import com.android.server.display.DisplayDeviceConfig;
+import com.android.server.display.TestUtils;
+import com.android.server.display.mode.DisplayModeDirector.BrightnessObserver;
+import com.android.server.display.mode.DisplayModeDirector.DesiredDisplayModeSpecs;
+import com.android.server.display.mode.DisplayModeDirector.Vote;
 import com.android.server.sensors.SensorManagerInternal;
 import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
 import com.android.server.statusbar.StatusBarManagerInternal;
@@ -126,6 +127,8 @@
     private static final int DISPLAY_ID = 0;
     private static final float TRANSITION_POINT = 0.763f;
 
+    private static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY;
+
     private Context mContext;
     private FakesInjector mInjector;
     private Handler mHandler;
@@ -2234,7 +2237,7 @@
                 ArgumentCaptor.forClass(IThermalEventListener.class);
 
         verify(mThermalServiceMock).registerThermalEventListenerWithType(
-            thermalEventListener.capture(), eq(Temperature.TYPE_SKIN));
+                thermalEventListener.capture(), eq(Temperature.TYPE_SKIN));
         final IThermalEventListener listener = thermalEventListener.getValue();
 
         // Verify that there is no skin temperature vote initially.
@@ -2548,7 +2551,7 @@
                     KEY_REFRESH_RATE_IN_HBM_HDR, String.valueOf(fps));
         }
 
-        void setBrightnessThrottlingData(String brightnessThrottlingData) {
+        public void setBrightnessThrottlingData(String brightnessThrottlingData) {
             putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                     KEY_BRIGHTNESS_THROTTLING_DATA, brightnessThrottlingData);
         }
diff --git a/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java b/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java
index 23d7082..be13753 100644
--- a/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/PendingJobQueueTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.job;
 
+import static android.app.job.JobInfo.NETWORK_TYPE_ANY;
+import static android.app.job.JobInfo.NETWORK_TYPE_NONE;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -525,7 +528,9 @@
             final boolean ui = random.nextBoolean();
             final boolean ej = !ui && random.nextBoolean();
             JobStatus job = createJobStatus("testPendingJobSorting_Random",
-                    createJobInfo(i).setExpedited(ej).setUserInitiated(ui), random.nextInt(250));
+                    createJobInfo(i).setExpedited(ej).setUserInitiated(ui)
+                            .setRequiredNetworkType(ui ? NETWORK_TYPE_ANY : NETWORK_TYPE_NONE),
+                    random.nextInt(250));
             job.enqueueTime = random.nextInt(1_000_000);
             jobQueue.add(job);
         }
@@ -562,7 +567,9 @@
                 final boolean ui = random.nextBoolean();
                 final boolean ej = !ui && random.nextBoolean();
                 JobStatus job = createJobStatus("testPendingJobSortingTransitivity",
-                        createJobInfo(i).setExpedited(ej).setUserInitiated(ui), random.nextInt(50));
+                        createJobInfo(i).setExpedited(ej).setUserInitiated(ui)
+                                .setRequiredNetworkType(ui ? NETWORK_TYPE_ANY : NETWORK_TYPE_NONE),
+                        random.nextInt(50));
                 job.enqueueTime = random.nextInt(1_000_000);
                 job.overrideState = random.nextInt(4);
                 jobQueue.add(job);
@@ -586,7 +593,8 @@
                 final boolean ui = random.nextFloat() < .02;
                 final boolean ej = !ui && random.nextFloat() < .03;
                 JobStatus job = createJobStatus("testPendingJobSortingTransitivity_Concentrated",
-                        createJobInfo(i).setExpedited(ej).setUserInitiated(ui),
+                        createJobInfo(i).setExpedited(ej).setUserInitiated(ui)
+                                .setRequiredNetworkType(ui ? NETWORK_TYPE_ANY : NETWORK_TYPE_NONE),
                         random.nextInt(20));
                 job.enqueueTime = random.nextInt(250);
                 job.overrideState = random.nextFloat() < .01
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 9686c38..1c33d0d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -165,10 +165,11 @@
     }
 
     @Override
-    protected void tieProfileLockToParent(int userId, LockscreenCredential password) {
+    protected void tieProfileLockToParent(int profileUserId, int parentUserId,
+            LockscreenCredential password) {
         Parcel parcel = Parcel.obtain();
         parcel.writeParcelable(password, 0);
-        mStorage.writeChildProfileLock(userId, parcel.marshall());
+        mStorage.writeChildProfileLock(profileUserId, parcel.marshall());
         parcel.recycle();
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/media/DeviceRouteControllerTest.java b/services/tests/servicestests/src/com/android/server/media/DeviceRouteControllerTest.java
new file mode 100644
index 0000000..24ed42c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/media/DeviceRouteControllerTest.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.media;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import android.annotation.IdRes;
+import android.content.Context;
+import android.content.res.Resources;
+import android.media.AudioManager;
+import android.media.AudioRoutesInfo;
+import android.media.IAudioRoutesObserver;
+import android.media.MediaRoute2Info;
+import android.os.RemoteException;
+import android.text.TextUtils;
+
+import com.android.internal.R;
+import com.android.server.audio.AudioService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.junit.runners.Parameterized;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Enclosed.class)
+public class DeviceRouteControllerTest {
+
+    private static final String DEFAULT_ROUTE_NAME = "default_route";
+    private static final String DEFAULT_HEADPHONES_NAME = "headphone";
+    private static final String DEFAULT_HEADSET_NAME = "headset";
+    private static final String DEFAULT_DOCK_NAME = "dock";
+    private static final String DEFAULT_HDMI_NAME = "hdmi";
+    private static final String DEFAULT_USB_NAME = "usb";
+    private static final int VOLUME_DEFAULT_VALUE = 0;
+    private static final int VOLUME_VALUE_SAMPLE_1 = 10;
+
+    private static AudioRoutesInfo createFakeBluetoothAudioRoute() {
+        AudioRoutesInfo btRouteInfo = new AudioRoutesInfo();
+        btRouteInfo.mainType = AudioRoutesInfo.MAIN_SPEAKER;
+        btRouteInfo.bluetoothName = "bt_device";
+        return btRouteInfo;
+    }
+
+    @RunWith(JUnit4.class)
+    public static class DefaultDeviceRouteValueTest {
+        @Mock
+        private Context mContext;
+        @Mock
+        private Resources mResources;
+        @Mock
+        private AudioManager mAudioManager;
+        @Mock
+        private AudioService mAudioService;
+        @Mock
+        private DeviceRouteController.OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+
+        @Before
+        public void setUp() {
+            MockitoAnnotations.initMocks(this);
+
+            when(mContext.getResources()).thenReturn(mResources);
+        }
+
+        @Test
+        public void initialize_noRoutesInfo_defaultRouteIsNotNull() {
+            // Mocking default_audio_route_name.
+            when(mResources.getText(R.string.default_audio_route_name))
+                    .thenReturn(DEFAULT_ROUTE_NAME);
+
+            // Default route should be initialized even when AudioService returns null.
+            when(mAudioService.startWatchingRoutes(any())).thenReturn(null);
+
+            DeviceRouteController deviceRouteController = new DeviceRouteController(
+                    mContext,
+                    mAudioManager,
+                    mAudioService,
+                    mOnDeviceRouteChangedListener
+            );
+
+            MediaRoute2Info actualMediaRoute = deviceRouteController.getDeviceRoute();
+
+            assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
+            assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_ROUTE_NAME))
+                    .isTrue();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+        }
+
+        @Test
+        public void initialize_bluetoothRouteAvailable_deviceRouteReturnsDefaultRoute() {
+            // Mocking default_audio_route_name.
+            when(mResources.getText(R.string.default_audio_route_name))
+                    .thenReturn(DEFAULT_ROUTE_NAME);
+
+            // This route should be ignored.
+            AudioRoutesInfo fakeBluetoothAudioRoute = createFakeBluetoothAudioRoute();
+            when(mAudioService.startWatchingRoutes(any())).thenReturn(fakeBluetoothAudioRoute);
+
+            DeviceRouteController deviceRouteController = new DeviceRouteController(
+                    mContext,
+                    mAudioManager,
+                    mAudioService,
+                    mOnDeviceRouteChangedListener
+            );
+
+            MediaRoute2Info actualMediaRoute = deviceRouteController.getDeviceRoute();
+
+            assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
+            assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_ROUTE_NAME))
+                    .isTrue();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+        }
+    }
+
+    @RunWith(Parameterized.class)
+    public static class DeviceRouteInitializationTest {
+
+        @Parameterized.Parameters
+        public static Collection<Object[]> data() {
+            return Arrays.asList(new Object[][] {
+                    {     /* expected res */
+                          com.android.internal.R.string.default_audio_route_name_headphones,
+                          /* expected name */
+                          DEFAULT_HEADPHONES_NAME,
+                          /* expected type */
+                          MediaRoute2Info.TYPE_WIRED_HEADPHONES,
+                          /* actual audio route type */
+                          AudioRoutesInfo.MAIN_HEADPHONES },
+                    {   /* expected res */
+                        com.android.internal.R.string.default_audio_route_name_headphones,
+                        /* expected name */
+                        DEFAULT_HEADSET_NAME,
+                        /* expected type */
+                        MediaRoute2Info.TYPE_WIRED_HEADSET,
+                        /* actual audio route type */
+                        AudioRoutesInfo.MAIN_HEADSET },
+                    {    /* expected res */
+                        R.string.default_audio_route_name_dock_speakers,
+                        /* expected name */
+                        DEFAULT_DOCK_NAME,
+                        /* expected type */
+                        MediaRoute2Info.TYPE_DOCK,
+                        /* actual audio route type */
+                        AudioRoutesInfo.MAIN_DOCK_SPEAKERS },
+                    {   /* expected res */
+                        R.string.default_audio_route_name_external_device,
+                        /* expected name */
+                        DEFAULT_HDMI_NAME,
+                        /* expected type */
+                        MediaRoute2Info.TYPE_HDMI,
+                        /* actual audio route type */
+                        AudioRoutesInfo.MAIN_HDMI },
+                    {   /* expected res */
+                        R.string.default_audio_route_name_usb,
+                        /* expected name */
+                        DEFAULT_USB_NAME,
+                        /* expected type */
+                        MediaRoute2Info.TYPE_USB_DEVICE,
+                        /* actual audio route type */
+                        AudioRoutesInfo.MAIN_USB }
+            });
+        }
+
+        @Mock
+        private Context mContext;
+        @Mock
+        private Resources mResources;
+        @Mock
+        private AudioManager mAudioManager;
+        @Mock
+        private AudioService mAudioService;
+        @Mock
+        private DeviceRouteController.OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+
+        @IdRes
+        private final int mExpectedRouteNameResource;
+        private final String mExpectedRouteNameValue;
+        private final int mExpectedRouteType;
+        private final int mActualAudioRouteType;
+
+        public DeviceRouteInitializationTest(int expectedRouteNameResource,
+                String expectedRouteNameValue,
+                int expectedMediaRouteType,
+                int actualAudioRouteType) {
+            this.mExpectedRouteNameResource = expectedRouteNameResource;
+            this.mExpectedRouteNameValue = expectedRouteNameValue;
+            this.mExpectedRouteType = expectedMediaRouteType;
+            this.mActualAudioRouteType = actualAudioRouteType;
+        }
+
+        @Before
+        public void setUp() {
+            MockitoAnnotations.initMocks(this);
+
+            when(mContext.getResources()).thenReturn(mResources);
+        }
+
+        @Test
+        public void initialize_wiredRouteAvailable_deviceRouteReturnsWiredRoute() {
+            // Mocking default_audio_route_name.
+            when(mResources.getText(R.string.default_audio_route_name))
+                    .thenReturn(DEFAULT_ROUTE_NAME);
+
+            // At first, WiredRouteController should initialize device
+            // route based on AudioService response.
+            AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+            audioRoutesInfo.mainType = mActualAudioRouteType;
+            when(mAudioService.startWatchingRoutes(any())).thenReturn(audioRoutesInfo);
+
+            when(mResources.getText(mExpectedRouteNameResource))
+                    .thenReturn(mExpectedRouteNameValue);
+
+            DeviceRouteController deviceRouteController = new DeviceRouteController(
+                    mContext,
+                    mAudioManager,
+                    mAudioService,
+                    mOnDeviceRouteChangedListener
+            );
+
+            MediaRoute2Info actualMediaRoute = deviceRouteController.getDeviceRoute();
+
+            assertThat(actualMediaRoute.getType()).isEqualTo(mExpectedRouteType);
+            assertThat(TextUtils.equals(actualMediaRoute.getName(), mExpectedRouteNameValue))
+                    .isTrue();
+            // Volume did not change, so it should be set to default value (0).
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+        }
+    }
+
+    @RunWith(JUnit4.class)
+    public static class VolumeAndDeviceRoutesChangesTest {
+        @Mock
+        private Context mContext;
+        @Mock
+        private Resources mResources;
+        @Mock
+        private AudioManager mAudioManager;
+        @Mock
+        private AudioService mAudioService;
+        @Mock
+        private DeviceRouteController.OnDeviceRouteChangedListener mOnDeviceRouteChangedListener;
+
+        @Captor
+        private ArgumentCaptor<IAudioRoutesObserver.Stub> mAudioRoutesObserverCaptor;
+
+        private DeviceRouteController mDeviceRouteController;
+        private IAudioRoutesObserver.Stub mAudioRoutesObserver;
+
+        @Before
+        public void setUp() {
+            MockitoAnnotations.initMocks(this);
+
+            when(mContext.getResources()).thenReturn(mResources);
+
+            when(mResources.getText(R.string.default_audio_route_name))
+                    .thenReturn(DEFAULT_ROUTE_NAME);
+
+            // Setting built-in speaker as default speaker.
+            AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+            audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_SPEAKER;
+            when(mAudioService.startWatchingRoutes(mAudioRoutesObserverCaptor.capture()))
+                    .thenReturn(audioRoutesInfo);
+
+            mDeviceRouteController = new DeviceRouteController(
+                    mContext,
+                    mAudioManager,
+                    mAudioService,
+                    mOnDeviceRouteChangedListener
+            );
+
+            mAudioRoutesObserver = mAudioRoutesObserverCaptor.getValue();
+        }
+
+        @Test
+        public void newDeviceConnects_wiredDevice_deviceRouteReturnsWiredDevice() {
+            // Connecting wired headset
+            AudioRoutesInfo audioRoutesInfo = new AudioRoutesInfo();
+            audioRoutesInfo.mainType = AudioRoutesInfo.MAIN_HEADPHONES;
+
+            when(mResources.getText(
+                    com.android.internal.R.string.default_audio_route_name_headphones))
+                    .thenReturn(DEFAULT_HEADPHONES_NAME);
+
+            // Simulating wired device being connected.
+            callAudioRoutesObserver(audioRoutesInfo);
+
+            MediaRoute2Info actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+
+            assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_WIRED_HEADPHONES);
+            assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_HEADPHONES_NAME))
+                    .isTrue();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+        }
+
+        @Test
+        public void newDeviceConnects_bluetoothDevice_deviceRouteReturnsBluetoothDevice() {
+            // Simulating bluetooth speaker being connected.
+            AudioRoutesInfo fakeBluetoothAudioRoute = createFakeBluetoothAudioRoute();
+            callAudioRoutesObserver(fakeBluetoothAudioRoute);
+
+            MediaRoute2Info actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+
+            assertThat(actualMediaRoute.getType()).isEqualTo(MediaRoute2Info.TYPE_BUILTIN_SPEAKER);
+            assertThat(TextUtils.equals(actualMediaRoute.getName(), DEFAULT_ROUTE_NAME))
+                    .isTrue();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+        }
+
+        @Test
+        public void updateVolume_differentValue_updatesDeviceRouteVolume() {
+            MediaRoute2Info actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_DEFAULT_VALUE);
+
+            assertThat(mDeviceRouteController.updateVolume(VOLUME_VALUE_SAMPLE_1)).isTrue();
+
+            actualMediaRoute = mDeviceRouteController.getDeviceRoute();
+            assertThat(actualMediaRoute.getVolume()).isEqualTo(VOLUME_VALUE_SAMPLE_1);
+        }
+
+        @Test
+        public void updateVolume_sameValue_returnsFalse() {
+            assertThat(mDeviceRouteController.updateVolume(VOLUME_VALUE_SAMPLE_1)).isTrue();
+            assertThat(mDeviceRouteController.updateVolume(VOLUME_VALUE_SAMPLE_1)).isFalse();
+        }
+
+        /**
+         * Simulates {@link IAudioRoutesObserver.Stub#dispatchAudioRoutesChanged(AudioRoutesInfo)}
+         * from {@link AudioService}. This happens when there is a wired route change,
+         * like a wired headset being connected.
+         *
+         * @param audioRoutesInfo updated state of connected wired device
+         */
+        private void callAudioRoutesObserver(AudioRoutesInfo audioRoutesInfo) {
+            try {
+                // this is a captured observer implementation
+                // from WiredRoutesController's AudioService#startWatchingRoutes call
+                mAudioRoutesObserver.dispatchAudioRoutesChanged(audioRoutesInfo);
+            } catch (RemoteException exception) {
+                // Should not happen since the object is mocked.
+                assertWithMessage("An unexpected RemoteException happened.").fail();
+            }
+        }
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 4a2e5d7..9fc46c5 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -86,7 +86,6 @@
 import android.telecom.TelecomManager;
 import android.telephony.TelephonyManager;
 import android.text.format.DateUtils;
-import android.util.Pair;
 import android.util.Range;
 
 import com.android.internal.app.ChooserActivity;
@@ -187,7 +186,6 @@
     private ShortcutInfo mShortcutInfo;
     private TestInjector mInjector;
     private TestLooper mLooper;
-    private TestPerPackageThrottler mShortcutThrottler;
 
     @Before
     public void setUp() throws PackageManager.NameNotFoundException {
@@ -277,9 +275,7 @@
 
         mInjector = new TestInjector();
         mLooper = new TestLooper();
-        mShortcutThrottler = new TestPerPackageThrottler();
-        mDataManager = new DataManager(mContext, mInjector, mLooper.getLooper(),
-                mShortcutThrottler);
+        mDataManager = new DataManager(mContext, mInjector, mLooper.getLooper());
         mDataManager.initialize();
 
         when(mShortcutServiceInternal.isSharingShortcut(anyInt(), anyString(), anyString(),
@@ -287,7 +283,10 @@
 
         mShortcutInfo = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mockGetShortcuts(Collections.singletonList(mShortcutInfo));
+        when(mShortcutServiceInternal.getShortcuts(
+                anyInt(), anyString(), anyLong(), anyString(), anyList(), any(), any(),
+                anyInt(), anyInt(), anyInt(), anyInt()))
+                .thenReturn(Collections.singletonList(mShortcutInfo));
         verify(mShortcutServiceInternal).addShortcutChangeCallback(
                 mShortcutChangeCallbackCaptor.capture());
         mShortcutChangeCallback = mShortcutChangeCallbackCaptor.getValue();
@@ -973,7 +972,6 @@
                 buildPerson());
         ShortcutInfo shortcut3 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc3",
                 buildPerson());
-        mockGetShortcuts(List.of(shortcut1, shortcut2, shortcut3));
         mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME,
                 Arrays.asList(shortcut1, shortcut2, shortcut3), UserHandle.of(USER_ID_PRIMARY));
         mShortcutChangeCallback.onShortcutsRemoved(TEST_PKG_NAME,
@@ -1225,6 +1223,7 @@
                     eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
         }
     }
+
     @Test
     public void testUncacheOldestCachedShortcut_missingNotificationEvents() {
         mDataManager.onUserUnlocked(USER_ID_PRIMARY);
@@ -1234,7 +1233,6 @@
             ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
                     buildPerson());
             shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
-            mockGetShortcuts(Collections.singletonList(shortcut));
             mShortcutChangeCallback.onShortcutsAddedOrUpdated(
                     TEST_PKG_NAME,
                     Collections.singletonList(shortcut),
@@ -1254,6 +1252,7 @@
                     eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
         }
     }
+
     @Test
     public void testUncacheOldestCachedShortcut_legacyConversation() {
         mDataManager.onUserUnlocked(USER_ID_PRIMARY);
@@ -1275,7 +1274,6 @@
             ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, shortcutId,
                     buildPerson());
             shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
-            mockGetShortcuts(Collections.singletonList(shortcut));
             mShortcutChangeCallback.onShortcutsAddedOrUpdated(
                     TEST_PKG_NAME,
                     Collections.singletonList(shortcut),
@@ -1313,8 +1311,7 @@
         mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
         byte[] payload = mDataManager.getBackupPayload(USER_ID_PRIMARY);
 
-        DataManager dataManager = new DataManager(
-                mContext, mInjector, mLooper.getLooper(), mShortcutThrottler);
+        DataManager dataManager = new DataManager(mContext, mInjector, mLooper.getLooper());
         dataManager.onUserUnlocked(USER_ID_PRIMARY);
         dataManager.restore(USER_ID_PRIMARY, payload);
         ConversationInfo conversationInfo = dataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
@@ -1726,13 +1723,6 @@
         return (queryFlags & flag) != 0;
     }
 
-    private void mockGetShortcuts(List<ShortcutInfo> shortcutInfoList) {
-        when(mShortcutServiceInternal.getShortcuts(
-                anyInt(), anyString(), anyLong(), anyString(), any(), any(), any(),
-                anyInt(), anyInt(), anyInt(), anyInt()))
-                .thenReturn(shortcutInfoList);
-    }
-
     // "Sends" a notification to a non-customized notification channel - the notification channel
     // is something generic like "messages" and the notification has a  shortcut id
     private void sendGenericNotification() {
@@ -1994,11 +1984,4 @@
             return mUsageStatsQueryHelper;
         }
     }
-
-    private static class TestPerPackageThrottler implements PerPackageThrottler {
-        @Override
-        public void scheduleDebounced(Pair<String, Integer> pkgUserId, Runnable runnable) {
-            runnable.run();
-        }
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/people/data/PerPackageThrottlerImplTest.java b/services/tests/servicestests/src/com/android/server/people/data/PerPackageThrottlerImplTest.java
deleted file mode 100644
index 672cbb9..0000000
--- a/services/tests/servicestests/src/com/android/server/people/data/PerPackageThrottlerImplTest.java
+++ /dev/null
@@ -1,67 +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.people.data;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.util.Pair;
-
-import com.android.server.testutils.OffsettableClock;
-import com.android.server.testutils.TestHandler;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-@RunWith(JUnit4.class)
-public class PerPackageThrottlerImplTest {
-    private static final int DEBOUNCE_INTERVAL = 500;
-    private static final String PKG_ONE = "pkg_one";
-    private static final String PKG_TWO = "pkg_two";
-    private static final int USER_ID = 10;
-
-    private final OffsettableClock mClock = new OffsettableClock.Stopped();
-    private final TestHandler mTestHandler = new TestHandler(null, mClock);
-    private PerPackageThrottlerImpl mThrottler;
-
-    @Before
-    public void setUp() {
-        mThrottler = new PerPackageThrottlerImpl(mTestHandler, DEBOUNCE_INTERVAL);
-    }
-
-    @Test
-    public void scheduleDebounced() {
-        AtomicBoolean pkgOneRan = new AtomicBoolean();
-        AtomicBoolean pkgTwoRan = new AtomicBoolean();
-
-        mThrottler.scheduleDebounced(new Pair<>(PKG_ONE, USER_ID), () -> pkgOneRan.set(true));
-        mThrottler.scheduleDebounced(new Pair<>(PKG_ONE, USER_ID), () -> pkgOneRan.set(true));
-        mThrottler.scheduleDebounced(new Pair<>(PKG_TWO, USER_ID), () -> pkgTwoRan.set(true));
-        mThrottler.scheduleDebounced(new Pair<>(PKG_TWO, USER_ID), () -> pkgTwoRan.set(true));
-
-        assertFalse(pkgOneRan.get());
-        assertFalse(pkgTwoRan.get());
-        mClock.fastForward(DEBOUNCE_INTERVAL);
-        mTestHandler.timeAdvance();
-        assertTrue(pkgOneRan.get());
-        assertTrue(pkgTwoRan.get());
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index b20c63c..0a718e3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -118,10 +118,12 @@
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
+import java.io.Writer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
@@ -4005,6 +4007,156 @@
         // TODO Check all other fields
     }
 
+    public void testSaveCorruptAndLoadUser() throws Exception {
+        // First, create some shortcuts and save.
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x16);
+            final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                    getTestContext().getResources(), R.drawable.icon2));
+
+            final ShortcutInfo si1 = makeShortcut(
+                    "s1",
+                    "title1-1",
+                    makeComponent(ShortcutActivity.class),
+                    icon1,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                            "key1", "val1", "nest", makeBundle("key", 123)),
+                    /* weight */ 10);
+
+            final ShortcutInfo si2 = makeShortcut(
+                    "s2",
+                    "title1-2",
+                    /* activity */ null,
+                    icon2,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                    /* weight */ 12);
+
+            assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
+
+            assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+            assertEquals(2, mManager.getRemainingCallCount());
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_16x64);
+            final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                    getTestContext().getResources(), R.drawable.icon2));
+
+            final ShortcutInfo si1 = makeShortcut(
+                    "s1",
+                    "title2-1",
+                    makeComponent(ShortcutActivity.class),
+                    icon1,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                            "key1", "val1", "nest", makeBundle("key", 123)),
+                    /* weight */ 10);
+
+            final ShortcutInfo si2 = makeShortcut(
+                    "s2",
+                    "title2-2",
+                    /* activity */ null,
+                    icon2,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                    /* weight */ 12);
+
+            assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
+
+            assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+            assertEquals(2, mManager.getRemainingCallCount());
+        });
+
+        mRunningUsers.put(USER_10, true);
+
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            final Icon icon1 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
+            final Icon icon2 = Icon.createWithBitmap(BitmapFactory.decodeResource(
+                    getTestContext().getResources(), R.drawable.icon2));
+
+            final ShortcutInfo si1 = makeShortcut(
+                    "s1",
+                    "title10-1-1",
+                    makeComponent(ShortcutActivity.class),
+                    icon1,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity2.class,
+                            "key1", "val1", "nest", makeBundle("key", 123)),
+                    /* weight */ 10);
+
+            final ShortcutInfo si2 = makeShortcut(
+                    "s2",
+                    "title10-1-2",
+                    /* activity */ null,
+                    icon2,
+                    makeIntent(Intent.ACTION_ASSIST, ShortcutActivity3.class),
+                    /* weight */ 12);
+
+            assertTrue(mManager.setDynamicShortcuts(list(si1, si2)));
+
+            assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
+            assertEquals(2, mManager.getRemainingCallCount());
+        });
+
+        // Save and corrupt the primary files.
+        mService.saveDirtyInfo();
+        try (Writer os = new FileWriter(mService.getUserFile(UserHandle.USER_SYSTEM))) {
+            os.write("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+                    + "<user locales=\"en\" last-app-scan-time2=\"14400000");
+        }
+        try (Writer os = new FileWriter(mService.getUserFile(USER_10))) {
+            os.write("<?xml version='1.0' encoding='utf");
+        }
+
+        // Restore.
+        initService();
+
+        // Before the load, the map should be empty.
+        assertEquals(0, mService.getShortcutsForTest().size());
+
+        // this will pre-load the per-user info.
+        mService.handleUnlockUser(UserHandle.USER_SYSTEM);
+
+        // Now it's loaded.
+        assertEquals(1, mService.getShortcutsForTest().size());
+
+        runWithCaller(CALLING_PACKAGE_1, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+                    mManager.getDynamicShortcuts()))), "s1", "s2");
+            assertEquals(2, mManager.getRemainingCallCount());
+
+            assertEquals("title1-1", getCallerShortcut("s1").getTitle());
+            assertEquals("title1-2", getCallerShortcut("s2").getTitle());
+        });
+        runWithCaller(CALLING_PACKAGE_2, UserHandle.USER_SYSTEM, () -> {
+            assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+                    mManager.getDynamicShortcuts()))), "s1", "s2");
+            assertEquals(2, mManager.getRemainingCallCount());
+
+            assertEquals("title2-1", getCallerShortcut("s1").getTitle());
+            assertEquals("title2-2", getCallerShortcut("s2").getTitle());
+        });
+
+        // Start another user
+        mService.handleUnlockUser(USER_10);
+
+        // Now the size is 2.
+        assertEquals(2, mService.getShortcutsForTest().size());
+
+        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+            assertShortcutIds(assertAllDynamic(assertAllHaveIntents(assertAllHaveIcon(
+                    mManager.getDynamicShortcuts()))), "s1", "s2");
+            assertEquals(2, mManager.getRemainingCallCount());
+
+            assertEquals("title10-1-1", getCallerShortcut("s1").getTitle());
+            assertEquals("title10-1-2", getCallerShortcut("s2").getTitle());
+        });
+
+        // Try stopping the user
+        mService.handleStopUser(USER_10);
+
+        // Now it's unloaded.
+        assertEquals(1, mService.getShortcutsForTest().size());
+
+        // TODO Check all other fields
+    }
+
     public void testCleanupPackage() {
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
             assertTrue(mManager.setDynamicShortcuts(list(
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
index 4434a32..32c9e75 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceShellCommandTest.java
@@ -121,4 +121,31 @@
         assertEquals("Couldn't get main user.", mOutStream.toString().trim());
     }
 
+    @Test
+    public void testCanSwitchToHeadlessSystemUser() {
+        doReturn(true).when(mUserManagerService).canSwitchToHeadlessSystemUser();
+        doReturn(mWriter).when(mCommand).getOutPrintWriter();
+
+        assertEquals(0, mCommand.exec(mBinder, in, out, err,
+                new String[]{"can-switch-to-headless-system-user"},
+                mShellCallback, mResultReceiver));
+
+        mWriter.flush();
+        assertEquals("true", mOutStream.toString().trim());
+    }
+
+
+    @Test
+    public void testIsMainUserPermanentAdmin() {
+        doReturn(false).when(mUserManagerService).isMainUserPermanentAdmin();
+        doReturn(mWriter).when(mCommand).getOutPrintWriter();
+
+        assertEquals(0, mCommand.exec(mBinder, in, out, err,
+                new String[]{"is-main-user-permanent-admin"}, mShellCallback, mResultReceiver));
+
+        mWriter.flush();
+        assertEquals("false", mOutStream.toString().trim());
+    }
+
+
 }
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index d71deaf..a0fb3de 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -16,7 +16,6 @@
 
 package com.android.server.power;
 
-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_FOREGROUND_SERVICE;
 import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -30,8 +29,6 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.AdditionalMatchers.gt;
-import static org.mockito.AdditionalMatchers.leq;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -153,9 +150,6 @@
     @Mock
     private InattentiveSleepWarningController mInattentiveSleepWarningControllerMock;
 
-    @Mock
-    private ActivityManagerInternal mActivityManagerInternal;
-
     private PowerManagerService mService;
     private ContextWrapper mContextSpy;
     private BatteryReceiver mBatteryReceiver;
@@ -211,7 +205,6 @@
         addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock);
         addLocalServiceMock(AttentionManagerInternal.class, mAttentionManagerInternalMock);
         addLocalServiceMock(DreamManagerInternal.class, mDreamManagerInternalMock);
-        addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternal);
 
         mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
         mResourcesSpy = spy(mContextSpy.getResources());
@@ -228,14 +221,6 @@
 
         mClock = new OffsettableClock.Stopped();
         mTestLooper = new TestLooper(mClock::now);
-
-        // Set up canHoldWakeLocksInDeepDoze.
-        // - procstate <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE -> true
-        // - procstate >  PROCESS_STATE_BOUND_FOREGROUND_SERVICE -> false
-        when(mActivityManagerInternal.canHoldWakeLocksInDeepDoze(
-                anyInt(), leq(PROCESS_STATE_BOUND_FOREGROUND_SERVICE))).thenReturn(true);
-        when(mActivityManagerInternal.canHoldWakeLocksInDeepDoze(
-                anyInt(), gt(PROCESS_STATE_BOUND_FOREGROUND_SERVICE))).thenReturn(false);
     }
 
     private PowerManagerService createService() {
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
index f803355..d78ab867 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
@@ -231,6 +231,10 @@
         setExternalStatsSyncLocked(mExternalStatsSync);
     }
 
+    @Override
+    public void writeSyncLocked() {
+    }
+
     public static class DummyExternalStatsSync implements ExternalStatsSync {
         public int flags = 0;
 
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 12f124e..6f6e2242 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -38,11 +38,12 @@
 import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
 
 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
-import static com.android.os.AtomsProto.DNDModeProto.CHANNELS_BYPASSING_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ENABLED_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ID_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.UID_FIELD_NUMBER;
-import static com.android.os.AtomsProto.DNDModeProto.ZEN_MODE_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.CHANNELS_BYPASSING_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ENABLED_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ID_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.UID_FIELD_NUMBER;
+import static com.android.os.dnd.DNDModeProto.ZEN_MODE_FIELD_NUMBER;
+import static com.android.os.dnd.DNDProtoEnums.ROOT_CONFIG;
 import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
 
 import static junit.framework.Assert.assertEquals;
@@ -95,7 +96,6 @@
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.service.notification.Condition;
-import android.service.notification.DNDModeProto;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.ScheduleInfo;
 import android.service.notification.ZenPolicy;
@@ -898,7 +898,7 @@
         assertEquals(n + 1, events.size());
         for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) {
             if (builder.getAtomId() == DND_MODE_RULE) {
-                if (builder.getInt(ZEN_MODE_FIELD_NUMBER) == DNDModeProto.ROOT_CONFIG) {
+                if (builder.getInt(ZEN_MODE_FIELD_NUMBER) == ROOT_CONFIG) {
                     assertTrue(builder.getBoolean(ENABLED_FIELD_NUMBER));
                     assertFalse(builder.getBoolean(CHANNELS_BYPASSING_FIELD_NUMBER));
                 }
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
index 3ecbbfeed..8f0a5e6 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
@@ -141,9 +141,9 @@
      */
     @Test
     public void testMetaN() throws RemoteException {
-        mPhoneWindowManager.overrideExpandNotificationsPanel();
+        mPhoneWindowManager.overrideTogglePanel();
         sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_N}, 0);
-        mPhoneWindowManager.assertExpandNotification();
+        mPhoneWindowManager.assertTogglePanel();
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index 6da9d0c..b693974 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -67,6 +67,7 @@
 import android.os.Vibrator;
 import android.service.dreams.DreamManagerInternal;
 import android.telecom.TelecomManager;
+import android.util.FeatureFlagUtils;
 import android.view.Display;
 import android.view.KeyEvent;
 import android.view.autofill.AutofillManagerInternal;
@@ -76,6 +77,7 @@
 import com.android.server.GestureLauncherService;
 import com.android.server.LocalServices;
 import com.android.server.input.InputManagerInternal;
+import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.vr.VrManagerInternal;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -114,6 +116,7 @@
     @Mock private Vibrator mVibrator;
     @Mock private PowerManager mPowerManager;
     @Mock private WindowManagerPolicy.WindowManagerFuncs mWindowManagerFuncsImpl;
+    @Mock private InputMethodManagerInternal mInputMethodManagerInternal;
     @Mock private AudioManagerInternal mAudioManagerInternal;
     @Mock private SearchManager mSearchManager;
 
@@ -184,6 +187,8 @@
                 () -> LocalServices.getService(eq(GestureLauncherService.class)));
         doReturn(null).when(() -> LocalServices.getService(eq(VrManagerInternal.class)));
         doReturn(null).when(() -> LocalServices.getService(eq(AutofillManagerInternal.class)));
+        LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
+        LocalServices.addService(InputMethodManagerInternal.class, mInputMethodManagerInternal);
 
         doReturn(mAppOpsManager).when(mContext).getSystemService(eq(AppOpsManager.class));
         doReturn(mDisplayManager).when(mContext).getSystemService(eq(DisplayManager.class));
@@ -242,6 +247,7 @@
 
     void tearDown() {
         mHandlerThread.quitSafely();
+        LocalServices.removeServiceForTest(InputMethodManagerInternal.class);
         mMockitoSession.finishMocking();
     }
 
@@ -322,12 +328,12 @@
         doReturn(true).when(mTelecomManager).endCall();
     }
 
-    void overrideExpandNotificationsPanel() {
+    void overrideTogglePanel() {
         // Can't directly mock on IStatusbarService, use spyOn and override the specific api.
         mPhoneWindowManager.getStatusBarService();
         spyOn(mPhoneWindowManager.mStatusBarService);
         try {
-            doNothing().when(mPhoneWindowManager.mStatusBarService).expandNotificationsPanel();
+            doNothing().when(mPhoneWindowManager.mStatusBarService).togglePanel();
         } catch (RemoteException e) {
             e.printStackTrace();
         }
@@ -417,7 +423,13 @@
 
     void assertSwitchKeyboardLayout(int direction) {
         waitForIdle();
-        verify(mWindowManagerFuncsImpl).switchKeyboardLayout(anyInt(), eq(direction));
+        if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_NEW_KEYBOARD_UI)) {
+            verify(mInputMethodManagerInternal).switchKeyboardLayout(eq(direction));
+            verify(mWindowManagerFuncsImpl, never()).switchKeyboardLayout(anyInt(), anyInt());
+        } else {
+            verify(mWindowManagerFuncsImpl).switchKeyboardLayout(anyInt(), eq(direction));
+            verify(mInputMethodManagerInternal, never()).switchKeyboardLayout(anyInt());
+        }
     }
 
     void assertTakeBugreport() {
@@ -428,9 +440,9 @@
         Assert.assertTrue(intentCaptor.getValue().getAction() == Intent.ACTION_BUG_REPORT);
     }
 
-    void assertExpandNotification() throws RemoteException {
+    void assertTogglePanel() throws RemoteException {
         waitForIdle();
-        verify(mPhoneWindowManager.mStatusBarService).expandNotificationsPanel();
+        verify(mPhoneWindowManager.mStatusBarService).togglePanel();
     }
 
     void assertToggleShortcutsMenu() {
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 d242a5f..cda8dd8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -117,6 +117,8 @@
 import org.mockito.ArgumentCaptor;
 
 import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
 
 /**
  * Tests for Size Compatibility mode.
@@ -172,6 +174,156 @@
     }
 
     @Test
+    public void testHorizontalReachabilityEnabledForTranslucentActivities() {
+        setUpDisplaySizeWithApp(2500, 1000);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        final LetterboxConfiguration config = mWm.mLetterboxConfiguration;
+        config.setTranslucentLetterboxingOverrideEnabled(true);
+        config.setLetterboxHorizontalPositionMultiplier(0.5f);
+        config.setIsHorizontalReachabilityEnabled(true);
+
+        // Opaque activity
+        prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+        addWindowToActivity(mActivity);
+        mActivity.mRootWindowContainer.performSurfacePlacement();
+
+        // Translucent Activity
+        final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+                .setLaunchedFromUid(mActivity.getUid())
+                .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+                .build();
+        doReturn(false).when(translucentActivity).fillsParent();
+        mTask.addChild(translucentActivity);
+
+        spyOn(translucentActivity.mLetterboxUiController);
+        doReturn(true).when(translucentActivity.mLetterboxUiController)
+                .shouldShowLetterboxUi(any());
+
+        addWindowToActivity(translucentActivity);
+        translucentActivity.mRootWindowContainer.performSurfacePlacement();
+
+        final Function<ActivityRecord, Rect> innerBoundsOf =
+                (ActivityRecord a) -> {
+                    final Rect bounds = new Rect();
+                    a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
+                    return bounds;
+                };
+        final Runnable checkLetterboxPositions = () -> assertEquals(innerBoundsOf.apply(mActivity),
+                innerBoundsOf.apply(translucentActivity));
+        final Runnable checkIsLeft = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).left).isEqualTo(0);
+        final Runnable checkIsRight = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).right).isEqualTo(2500);
+        final Runnable checkIsCentered = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).left > 0
+                        && innerBoundsOf.apply(translucentActivity).right < 2500).isTrue();
+
+        final Consumer<Integer> doubleClick =
+                (Integer x) -> {
+                    mActivity.mLetterboxUiController.handleHorizontalDoubleTap(x);
+                    mActivity.mRootWindowContainer.performSurfacePlacement();
+                };
+
+        // Initial state
+        checkIsCentered.run();
+
+        // Double-click left
+        doubleClick.accept(/* x */ 10);
+        checkLetterboxPositions.run();
+        checkIsLeft.run();
+
+        // Double-click right
+        doubleClick.accept(/* x */ 1990);
+        checkLetterboxPositions.run();
+        checkIsCentered.run();
+
+        // Double-click right
+        doubleClick.accept(/* x */ 1990);
+        checkLetterboxPositions.run();
+        checkIsRight.run();
+
+        // Double-click left
+        doubleClick.accept(/* x */ 10);
+        checkLetterboxPositions.run();
+        checkIsCentered.run();
+    }
+
+    @Test
+    public void testVerticalReachabilityEnabledForTranslucentActivities() {
+        setUpDisplaySizeWithApp(1000, 2500);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+        final LetterboxConfiguration config = mWm.mLetterboxConfiguration;
+        config.setTranslucentLetterboxingOverrideEnabled(true);
+        config.setLetterboxVerticalPositionMultiplier(0.5f);
+        config.setIsVerticalReachabilityEnabled(true);
+
+        // Opaque activity
+        prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
+        addWindowToActivity(mActivity);
+        mActivity.mRootWindowContainer.performSurfacePlacement();
+
+        // Translucent Activity
+        final ActivityRecord translucentActivity = new ActivityBuilder(mAtm)
+                .setLaunchedFromUid(mActivity.getUid())
+                .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE)
+                .build();
+        doReturn(false).when(translucentActivity).fillsParent();
+        mTask.addChild(translucentActivity);
+
+        spyOn(translucentActivity.mLetterboxUiController);
+        doReturn(true).when(translucentActivity.mLetterboxUiController)
+                .shouldShowLetterboxUi(any());
+
+        addWindowToActivity(translucentActivity);
+        translucentActivity.mRootWindowContainer.performSurfacePlacement();
+
+        final Function<ActivityRecord, Rect> innerBoundsOf =
+                (ActivityRecord a) -> {
+                    final Rect bounds = new Rect();
+                    a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
+                    return bounds;
+                };
+        final Runnable checkLetterboxPositions = () -> assertEquals(innerBoundsOf.apply(mActivity),
+                innerBoundsOf.apply(translucentActivity));
+        final Runnable checkIsTop = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).top).isEqualTo(0);
+        final Runnable checkIsBottom = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).bottom).isEqualTo(2500);
+        final Runnable checkIsCentered = () -> assertThat(
+                innerBoundsOf.apply(translucentActivity).top > 0
+                        && innerBoundsOf.apply(translucentActivity).bottom < 2500).isTrue();
+
+        final Consumer<Integer> doubleClick =
+                (Integer y) -> {
+                    mActivity.mLetterboxUiController.handleVerticalDoubleTap(y);
+                    mActivity.mRootWindowContainer.performSurfacePlacement();
+                };
+
+        // Initial state
+        checkIsCentered.run();
+
+        // Double-click top
+        doubleClick.accept(/* y */ 10);
+        checkLetterboxPositions.run();
+        checkIsTop.run();
+
+        // Double-click bottom
+        doubleClick.accept(/* y */ 1990);
+        checkLetterboxPositions.run();
+        checkIsCentered.run();
+
+        // Double-click bottom
+        doubleClick.accept(/* y */ 1990);
+        checkLetterboxPositions.run();
+        checkIsBottom.run();
+
+        // Double-click top
+        doubleClick.accept(/* y */ 10);
+        checkLetterboxPositions.run();
+        checkIsCentered.run();
+    }
+
+    @Test
     public void testApplyStrategyToTranslucentActivities() {
         mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
         setUpDisplaySizeWithApp(2000, 1000);
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 d7e4c55..169586e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -1023,7 +1023,7 @@
         RunningTaskInfo mInfo;
 
         @Override
-        public void addStartingWindow(StartingWindowInfo info) { }
+        public void addStartingWindow(StartingWindowInfo info, IBinder appToken) { }
         @Override
         public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) { }
         @Override
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 fafe90a..323894ca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1583,10 +1583,10 @@
         }
 
         @Override
-        public void addStartingWindow(StartingWindowInfo info) {
+        public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
             synchronized (mWMService.mGlobalLock) {
                 final ActivityRecord activity = mWMService.mRoot.getActivityRecord(
-                        info.appToken);
+                        appToken);
                 IWindow iWindow = mock(IWindow.class);
                 doReturn(mock(IBinder.class)).when(iWindow).asBinder();
                 final WindowState window = WindowTestsBase.createWindow(null,
@@ -1596,8 +1596,8 @@
                         iWindow,
                         mPowerManagerWrapper);
                 activity.mStartingWindow = window;
-                mAppWindowMap.put(info.appToken, window);
-                mTaskAppMap.put(info.taskInfo.taskId, info.appToken);
+                mAppWindowMap.put(appToken, window);
+                mTaskAppMap.put(info.taskInfo.taskId, appToken);
             }
             if (mRunnableWhenAddingSplashScreen != null) {
                 mRunnableWhenAddingSplashScreen.run();
diff --git a/services/usage/java/com/android/server/usage/TEST_MAPPING b/services/usage/java/com/android/server/usage/TEST_MAPPING
index 1c0c71b..a3fe6f2 100644
--- a/services/usage/java/com/android/server/usage/TEST_MAPPING
+++ b/services/usage/java/com/android/server/usage/TEST_MAPPING
@@ -18,9 +18,7 @@
           "exclude-filter": "com.android.server.usage.StorageStatsServiceTest"
         }
       ]
-    }
-  ],
-  "presubmit-large": [
+    },
     {
       "name": "CtsUsageStatsTestCases",
       "options": [
diff --git a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
index 0dcf8ce..b1cd994 100644
--- a/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbDirectMidiDevice.java
@@ -19,7 +19,6 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.hardware.usb.UsbConfiguration;
-import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbDeviceConnection;
 import android.hardware.usb.UsbEndpoint;
@@ -35,9 +34,12 @@
 import android.service.usb.UsbDirectMidiDeviceProto;
 import android.util.Log;
 
+import com.android.internal.midi.MidiEventMultiScheduler;
 import com.android.internal.midi.MidiEventScheduler;
 import com.android.internal.midi.MidiEventScheduler.MidiEvent;
 import com.android.internal.util.dump.DualDumpOutputStream;
+import com.android.server.usb.descriptors.UsbACMidi10Endpoint;
+import com.android.server.usb.descriptors.UsbDescriptor;
 import com.android.server.usb.descriptors.UsbDescriptorParser;
 import com.android.server.usb.descriptors.UsbEndpointDescriptor;
 import com.android.server.usb.descriptors.UsbInterfaceDescriptor;
@@ -45,6 +47,7 @@
 
 import libcore.io.IoUtils;
 
+import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -56,7 +59,7 @@
  */
 public final class UsbDirectMidiDevice implements Closeable {
     private static final String TAG = "UsbDirectMidiDevice";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;
 
     private Context mContext;
     private String mName;
@@ -74,9 +77,6 @@
 
     private MidiDeviceServer mServer;
 
-    // event schedulers for each input port of the physical device
-    private MidiEventScheduler[] mEventSchedulers;
-
     // Timeout for sending a packet to a device.
     // If bulkTransfer times out, retry sending the packet up to 20 times.
     private static final int BULK_TRANSFER_TIMEOUT_MILLISECONDS = 50;
@@ -86,8 +86,21 @@
     private static final int THREAD_JOIN_TIMEOUT_MILLISECONDS = 200;
 
     private ArrayList<UsbDeviceConnection> mUsbDeviceConnections;
+
+    // Array of endpoints by device connection.
     private ArrayList<ArrayList<UsbEndpoint>> mInputUsbEndpoints;
     private ArrayList<ArrayList<UsbEndpoint>> mOutputUsbEndpoints;
+
+    // Array of cable counts by device connection.
+    // Each number here maps to an entry in mInputUsbEndpoints or mOutputUsbEndpoints.
+    // This is needed because this info is part of UsbEndpointDescriptor but not UsbEndpoint.
+    private ArrayList<ArrayList<Integer>> mInputUsbEndpointCableCounts;
+    private ArrayList<ArrayList<Integer>> mOutputUsbEndpointCableCounts;
+
+    // Array of event schedulers by device connection.
+    // Each number here maps to an entry in mOutputUsbEndpoints.
+    private ArrayList<ArrayList<MidiEventMultiScheduler>> mMidiEventMultiSchedulers;
+
     private ArrayList<Thread> mThreads;
 
     private UsbMidiBlockParser mMidiBlockParser = new UsbMidiBlockParser();
@@ -97,8 +110,6 @@
     private boolean mIsOpen;
     private boolean mServerAvailable;
 
-    private UsbMidiPacketConverter mUsbMidiPacketConverter;
-
     private PowerBoostSetter mPowerBoostSetter = null;
 
     private static final byte MESSAGE_TYPE_MIDI_1_CHANNEL_VOICE = 0x02;
@@ -238,9 +249,9 @@
                         interfaceDescriptor.getEndpointDescriptor(endpointIndex);
                 // 0 is output, 1 << 7 is input.
                 if (endpoint.getDirection() == 0) {
-                    numOutputs++;
+                    numOutputs += getNumJacks(endpoint);
                 } else {
-                    numInputs++;
+                    numInputs += getNumJacks(endpoint);
                 }
             }
         }
@@ -307,19 +318,21 @@
         Log.d(TAG, "openLocked()");
         UsbManager manager = mContext.getSystemService(UsbManager.class);
 
-        // Converting from raw MIDI to USB MIDI is not thread-safe.
-        // UsbMidiPacketConverter creates a converter from raw MIDI
-        // to USB MIDI for each USB output.
-        mUsbMidiPacketConverter = new UsbMidiPacketConverter(mNumOutputs);
-
         mUsbDeviceConnections = new ArrayList<UsbDeviceConnection>();
         mInputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>();
         mOutputUsbEndpoints = new ArrayList<ArrayList<UsbEndpoint>>();
+        mInputUsbEndpointCableCounts = new ArrayList<ArrayList<Integer>>();
+        mOutputUsbEndpointCableCounts = new ArrayList<ArrayList<Integer>>();
+        mMidiEventMultiSchedulers = new ArrayList<ArrayList<MidiEventMultiScheduler>>();
         mThreads = new ArrayList<Thread>();
 
         for (int interfaceIndex = 0; interfaceIndex < mUsbInterfaces.size(); interfaceIndex++) {
             ArrayList<UsbEndpoint> inputEndpoints = new ArrayList<UsbEndpoint>();
             ArrayList<UsbEndpoint> outputEndpoints = new ArrayList<UsbEndpoint>();
+            ArrayList<Integer> inputEndpointCableCounts = new ArrayList<Integer>();
+            ArrayList<Integer> outputEndpointCableCounts = new ArrayList<Integer>();
+            ArrayList<MidiEventMultiScheduler> midiEventMultiSchedulers =
+                    new ArrayList<MidiEventMultiScheduler>();
             UsbInterfaceDescriptor interfaceDescriptor = mUsbInterfaces.get(interfaceIndex);
             for (int endpointIndex = 0; endpointIndex < interfaceDescriptor.getNumEndpoints();
                     endpointIndex++) {
@@ -328,8 +341,13 @@
                 // 0 is output, 1 << 7 is input.
                 if (endpoint.getDirection() == 0) {
                     outputEndpoints.add(endpoint.toAndroid(mParser));
+                    outputEndpointCableCounts.add(getNumJacks(endpoint));
+                    MidiEventMultiScheduler scheduler =
+                            new MidiEventMultiScheduler(getNumJacks(endpoint));
+                    midiEventMultiSchedulers.add(scheduler);
                 } else {
                     inputEndpoints.add(endpoint.toAndroid(mParser));
+                    inputEndpointCableCounts.add(getNumJacks(endpoint));
                 }
             }
             if (!outputEndpoints.isEmpty() || !inputEndpoints.isEmpty()) {
@@ -341,40 +359,69 @@
                 mUsbDeviceConnections.add(connection);
                 mInputUsbEndpoints.add(inputEndpoints);
                 mOutputUsbEndpoints.add(outputEndpoints);
+                mInputUsbEndpointCableCounts.add(inputEndpointCableCounts);
+                mOutputUsbEndpointCableCounts.add(outputEndpointCableCounts);
+                mMidiEventMultiSchedulers.add(midiEventMultiSchedulers);
             }
         }
 
-        mEventSchedulers = new MidiEventScheduler[mNumOutputs];
-
-        for (int i = 0; i < mNumOutputs; i++) {
-            MidiEventScheduler scheduler = new MidiEventScheduler();
-            mEventSchedulers[i] = scheduler;
-            mMidiInputPortReceivers[i].setReceiver(scheduler.getReceiver());
+        // Set up event schedulers
+        int outputIndex = 0;
+        for (int connectionIndex = 0; connectionIndex < mMidiEventMultiSchedulers.size();
+                connectionIndex++) {
+            for (int endpointIndex = 0;
+                    endpointIndex < mMidiEventMultiSchedulers.get(connectionIndex).size();
+                    endpointIndex++) {
+                int cableCount =
+                        mOutputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
+                MidiEventMultiScheduler multiScheduler =
+                        mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
+                for (int cableNumber = 0; cableNumber < cableCount; cableNumber++) {
+                    MidiEventScheduler scheduler = multiScheduler.getEventScheduler(cableNumber);
+                    mMidiInputPortReceivers[outputIndex].setReceiver(scheduler.getReceiver());
+                    outputIndex++;
+                }
+            }
         }
 
         final MidiReceiver[] outputReceivers = mServer.getOutputPortReceivers();
 
         // Create input thread for each input port of the physical device
-        int portNumber = 0;
+        int portStartNumber = 0;
         for (int connectionIndex = 0; connectionIndex < mInputUsbEndpoints.size();
                 connectionIndex++) {
             for (int endpointIndex = 0;
                     endpointIndex < mInputUsbEndpoints.get(connectionIndex).size();
                     endpointIndex++) {
+                // Each USB endpoint maps to one or more outputReceivers. USB MIDI data from an
+                // endpoint should be sent to the appropriate outputReceiver. A new thread is
+                // created and waits for incoming USB data. Once the data is received, it is added
+                // to the packet converter. The packet converter acts as an inverse multiplexer.
+                // With a for loop, data is pulled per cable and sent to the correct output
+                // receiver. The first byte of each legacy MIDI 1.0 USB message indicates which
+                // cable the data should be used and is how the reverse multiplexer directs data.
+                // For MIDI UMP endpoints, a multiplexer is not needed as we are just swapping
+                // the endianness of the packets.
                 final UsbDeviceConnection connectionFinal =
                         mUsbDeviceConnections.get(connectionIndex);
                 final UsbEndpoint endpointFinal =
                         mInputUsbEndpoints.get(connectionIndex).get(endpointIndex);
-                final int portFinal = portNumber;
+                final int portStartFinal = portStartNumber;
+                final int cableCountFinal =
+                        mInputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
 
-                Thread newThread = new Thread("UsbDirectMidiDevice input thread " + portFinal) {
+                Thread newThread = new Thread("UsbDirectMidiDevice input thread "
+                        + portStartFinal) {
                     @Override
                     public void run() {
                         final UsbRequest request = new UsbRequest();
+                        final UsbMidiPacketConverter packetConverter = new UsbMidiPacketConverter();
+                        packetConverter.createDecoders(cableCountFinal);
                         try {
                             request.initialize(connectionFinal, endpointFinal);
                             byte[] inputBuffer = new byte[endpointFinal.getMaxPacketSize()];
-                            while (true) {
+                            boolean keepGoing = true;
+                            while (keepGoing) {
                                 if (Thread.currentThread().interrupted()) {
                                     Log.w(TAG, "input thread interrupted");
                                     break;
@@ -404,42 +451,56 @@
                                         logByteArray("Input before conversion ", inputBuffer,
                                                 0, bytesRead);
                                     }
+
+                                    // Add packets into the packet decoder.
+                                    if (!mIsUniversalMidiDevice) {
+                                        packetConverter.decodeMidiPackets(inputBuffer, bytesRead);
+                                    }
+
                                     byte[] convertedArray;
-                                    if (mIsUniversalMidiDevice) {
-                                        // For USB, each 32 bit word of a UMP is
-                                        // sent with the least significant byte first.
-                                        convertedArray = swapEndiannessPerWord(inputBuffer,
-                                                bytesRead);
-                                    } else {
-                                        if (mUsbMidiPacketConverter == null) {
-                                            Log.w(TAG, "mUsbMidiPacketConverter is null");
+                                    for (int cableNumber = 0; cableNumber < cableCountFinal;
+                                            cableNumber++) {
+                                        if (mIsUniversalMidiDevice) {
+                                            // For USB, each 32 bit word of a UMP is
+                                            // sent with the least significant byte first.
+                                            convertedArray = swapEndiannessPerWord(inputBuffer,
+                                                    bytesRead);
+                                        } else {
+                                            convertedArray =
+                                                    packetConverter.pullDecodedMidiPackets(
+                                                            cableNumber);
+                                        }
+
+                                        if (DEBUG) {
+                                            logByteArray("Input " + cableNumber
+                                                    + " after conversion ", convertedArray, 0,
+                                                    convertedArray.length);
+                                        }
+
+                                        if (convertedArray.length == 0) {
+                                            continue;
+                                        }
+
+                                        if ((outputReceivers == null)
+                                                || (outputReceivers[portStartFinal + cableNumber]
+                                                == null)) {
+                                            Log.w(TAG, "outputReceivers is null");
+                                            keepGoing = false;
                                             break;
                                         }
-                                        convertedArray =
-                                                mUsbMidiPacketConverter.usbMidiToRawMidi(
-                                                         inputBuffer, bytesRead);
-                                    }
+                                        outputReceivers[portStartFinal + cableNumber].send(
+                                                convertedArray, 0, convertedArray.length,
+                                                timestamp);
 
-                                    if (DEBUG) {
-                                        logByteArray("Input after conversion ", convertedArray,
-                                                0, convertedArray.length);
-                                    }
-
-                                    if ((outputReceivers == null)
-                                            || (outputReceivers[portFinal] == null)) {
-                                        Log.w(TAG, "outputReceivers is null");
-                                        break;
-                                    }
-                                    outputReceivers[portFinal].send(convertedArray, 0,
-                                            convertedArray.length, timestamp);
-
-                                    // Boost power if there seems to be a voice message.
-                                    // For legacy devices, boost when message is more than size 1.
-                                    // For UMP devices, boost for channel voice messages.
-                                    if ((mPowerBoostSetter != null && convertedArray.length > 1)
-                                            && (!mIsUniversalMidiDevice
-                                            || isChannelVoiceMessage(convertedArray))) {
-                                        mPowerBoostSetter.boostPower();
+                                        // Boost power if there seems to be a voice message.
+                                        // For legacy devices, boost if message length > 1.
+                                        // For UMP devices, boost for channel voice messages.
+                                        if ((mPowerBoostSetter != null
+                                                && convertedArray.length > 1)
+                                                && (!mIsUniversalMidiDevice
+                                                || isChannelVoiceMessage(convertedArray))) {
+                                            mPowerBoostSetter.boostPower();
+                                        }
                                     }
                                 }
                             }
@@ -455,64 +516,93 @@
                 };
                 newThread.start();
                 mThreads.add(newThread);
-                portNumber++;
+                portStartNumber += cableCountFinal;
             }
         }
 
         // Create output thread for each output port of the physical device
-        portNumber = 0;
+        portStartNumber = 0;
         for (int connectionIndex = 0; connectionIndex < mOutputUsbEndpoints.size();
                 connectionIndex++) {
             for (int endpointIndex = 0;
                     endpointIndex < mOutputUsbEndpoints.get(connectionIndex).size();
                     endpointIndex++) {
+                // Each USB endpoint maps to one or more MIDI ports. Each port has an event
+                // scheduler that is used to pull incoming raw MIDI bytes from Android apps.
+                // With a MidiEventMultiScheduler, data can be pulled if any of the schedulers
+                // have new incoming data. This data is then packaged as USB MIDI packets before
+                // getting sent through USB. One thread will be created per endpoint that pulls
+                // data from all relevant event schedulers. Raw MIDI from the event schedulers
+                // will be converted to the correct USB MIDI format before getting sent through
+                // USB.
+
                 final UsbDeviceConnection connectionFinal =
                         mUsbDeviceConnections.get(connectionIndex);
                 final UsbEndpoint endpointFinal =
                         mOutputUsbEndpoints.get(connectionIndex).get(endpointIndex);
-                final int portFinal = portNumber;
-                final MidiEventScheduler eventSchedulerFinal = mEventSchedulers[portFinal];
+                final int portStartFinal = portStartNumber;
+                final int cableCountFinal =
+                        mOutputUsbEndpointCableCounts.get(connectionIndex).get(endpointIndex);
+                final MidiEventMultiScheduler multiSchedulerFinal =
+                            mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
 
-                Thread newThread = new Thread("UsbDirectMidiDevice output thread " + portFinal) {
+                Thread newThread = new Thread("UsbDirectMidiDevice output write thread "
+                        + portStartFinal) {
                     @Override
                     public void run() {
                         try {
-                            while (true) {
-                                if (Thread.currentThread().interrupted()) {
-                                    Log.w(TAG, "output thread interrupted");
+                            final ByteArrayOutputStream midi2ByteStream =
+                                    new ByteArrayOutputStream();
+                            final UsbMidiPacketConverter packetConverter =
+                                    new UsbMidiPacketConverter();
+                            packetConverter.createEncoders(cableCountFinal);
+                            boolean isInterrupted = false;
+                            while (!isInterrupted) {
+                                boolean wasSuccessful = multiSchedulerFinal.waitNextEvent();
+                                if (!wasSuccessful) {
+                                    Log.d(TAG, "output thread closed");
                                     break;
                                 }
-                                MidiEvent event;
-                                try {
-                                    event = (MidiEvent) eventSchedulerFinal.waitNextEvent();
-                                } catch (InterruptedException e) {
-                                    Log.w(TAG, "event scheduler interrupted");
-                                    break;
-                                }
-                                if (event == null) {
-                                    Log.w(TAG, "event is null");
-                                    break;
-                                }
-
-                                if (DEBUG) {
-                                    logByteArray("Output before conversion ", event.data, 0,
-                                            event.count);
-                                }
-
-                                byte[] convertedArray;
-                                if (mIsUniversalMidiDevice) {
-                                    // For USB, each 32 bit word of a UMP is
-                                    // sent with the least significant byte first.
-                                    convertedArray = swapEndiannessPerWord(event.data,
-                                            event.count);
-                                } else {
-                                    if (mUsbMidiPacketConverter == null) {
-                                        Log.w(TAG, "mUsbMidiPacketConverter is null");
-                                        break;
+                                long now = System.nanoTime();
+                                for (int cableNumber = 0; cableNumber < cableCountFinal;
+                                        cableNumber++) {
+                                    MidiEventScheduler eventScheduler =
+                                            multiSchedulerFinal.getEventScheduler(cableNumber);
+                                    MidiEvent event =
+                                            (MidiEvent) eventScheduler.getNextEvent(now);
+                                    while (event != null) {
+                                        if (DEBUG) {
+                                            logByteArray("Output before conversion ",
+                                                    event.data, 0, event.count);
+                                        }
+                                        if (mIsUniversalMidiDevice) {
+                                            // For USB, each 32 bit word of a UMP is
+                                            // sent with the least significant byte first.
+                                            byte[] convertedArray = swapEndiannessPerWord(
+                                                    event.data, event.count);
+                                            midi2ByteStream.write(convertedArray, 0,
+                                                    convertedArray.length);
+                                        } else {
+                                            packetConverter.encodeMidiPackets(event.data,
+                                                    event.count, cableNumber);
+                                        }
+                                        eventScheduler.addEventToPool(event);
+                                        event = (MidiEvent) eventScheduler.getNextEvent(now);
                                     }
+                                }
+
+                                if (Thread.currentThread().interrupted()) {
+                                    Log.d(TAG, "output thread interrupted");
+                                    break;
+                                }
+
+                                byte[] convertedArray = new byte[0];
+                                if (mIsUniversalMidiDevice) {
+                                    convertedArray = midi2ByteStream.toByteArray();
+                                    midi2ByteStream.reset();
+                                } else {
                                     convertedArray =
-                                            mUsbMidiPacketConverter.rawMidiToUsbMidi(
-                                                     event.data, event.count, portFinal);
+                                            packetConverter.pullEncodedMidiPackets();
                                 }
 
                                 if (DEBUG) {
@@ -520,7 +610,6 @@
                                             convertedArray.length);
                                 }
 
-                                boolean isInterrupted = false;
                                 // Split the packet into multiple if they are greater than the
                                 // endpoint's max packet size.
                                 for (int curPacketStart = 0;
@@ -558,11 +647,9 @@
                                         }
                                     }
                                 }
-                                if (isInterrupted == true) {
-                                    break;
-                                }
-                                eventSchedulerFinal.addEventToPool(event);
                             }
+                        } catch (InterruptedException e) {
+                            Log.w(TAG, "output thread: ", e);
                         } catch (NullPointerException e) {
                             Log.e(TAG, "output thread: ", e);
                         }
@@ -571,7 +658,7 @@
                 };
                 newThread.start();
                 mThreads.add(newThread);
-                portNumber++;
+                portStartNumber += cableCountFinal;
             }
         }
 
@@ -667,11 +754,21 @@
         }
         mThreads = null;
 
-        for (int i = 0; i < mEventSchedulers.length; i++) {
+        for (int i = 0; i < mMidiInputPortReceivers.length; i++) {
             mMidiInputPortReceivers[i].setReceiver(null);
-            mEventSchedulers[i].close();
         }
-        mEventSchedulers = null;
+
+        for (int connectionIndex = 0; connectionIndex < mMidiEventMultiSchedulers.size();
+                connectionIndex++) {
+            for (int endpointIndex = 0;
+                    endpointIndex < mMidiEventMultiSchedulers.get(connectionIndex).size();
+                    endpointIndex++) {
+                MidiEventMultiScheduler multiScheduler =
+                        mMidiEventMultiSchedulers.get(connectionIndex).get(endpointIndex);
+                multiScheduler.close();
+            }
+        }
+        mMidiEventMultiSchedulers = null;
 
         for (UsbDeviceConnection connection : mUsbDeviceConnections) {
             connection.close();
@@ -679,8 +776,8 @@
         mUsbDeviceConnections = null;
         mInputUsbEndpoints = null;
         mOutputUsbEndpoints = null;
-
-        mUsbMidiPacketConverter = null;
+        mInputUsbEndpointCableCounts = null;
+        mOutputUsbEndpointCableCounts = null;
 
         mIsOpen = false;
     }
@@ -788,4 +885,19 @@
         return messageType == MESSAGE_TYPE_MIDI_1_CHANNEL_VOICE
                 || messageType == MESSAGE_TYPE_MIDI_2_CHANNEL_VOICE;
     }
+
+    // Returns the number of jacks for MIDI 1.0 endpoints.
+    // For MIDI 2.0 endpoints, this concept does not exist and each endpoint should be treated as
+    // one port.
+    private int getNumJacks(UsbEndpointDescriptor usbEndpointDescriptor) {
+        UsbDescriptor classSpecificEndpointDescriptor =
+                usbEndpointDescriptor.getClassSpecificEndpointDescriptor();
+        if (classSpecificEndpointDescriptor != null
+                && (classSpecificEndpointDescriptor instanceof UsbACMidi10Endpoint)) {
+            UsbACMidi10Endpoint midiEndpoint =
+                    (UsbACMidi10Endpoint) classSpecificEndpointDescriptor;
+            return midiEndpoint.getNumJacks();
+        }
+        return 1;
+    }
 }
diff --git a/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java b/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
index 56bb236..65d7a41 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiPacketConverter.java
@@ -16,12 +16,17 @@
 
 package com.android.server.usb;
 
+import android.util.Log;
+
 import java.io.ByteArrayOutputStream;
 
 /**
- * Converts between MIDI packets and USB MIDI 1.0 packets.
+ * Converts between raw MIDI packets and USB MIDI 1.0 packets.
+ * This is NOT thread-safe. Please handle locking outside this function for multiple threads.
+ * For data mapping to an invalid cable number, this converter will use the first cable.
  */
 public class UsbMidiPacketConverter {
+    private static final String TAG = "UsbMidiPacketConverter";
 
     // Refer to Table 4-1 in USB MIDI 1.0 spec.
     private static final int[] PAYLOAD_SIZE = new int[]{
@@ -74,54 +79,133 @@
     private static final byte SYSEX_START_EXCLUSIVE = (byte) 0xF0;
     private static final byte SYSEX_END_EXCLUSIVE = (byte) 0xF7;
 
-    private UsbMidiDecoder mUsbMidiDecoder = new UsbMidiDecoder();
     private UsbMidiEncoder[] mUsbMidiEncoders;
+    private ByteArrayOutputStream mEncoderOutputStream = new ByteArrayOutputStream();
 
-    public UsbMidiPacketConverter(int numEncoders) {
-        mUsbMidiEncoders = new UsbMidiEncoder[numEncoders];
-        for (int i = 0; i < numEncoders; i++) {
-            mUsbMidiEncoders[i] = new UsbMidiEncoder();
-        }
-    }
+    private UsbMidiDecoder mUsbMidiDecoder;
 
     /**
-     * Converts a USB MIDI array into a raw MIDI array.
+     * Creates encoders.
      *
-     * @param usbMidiBytes the USB MIDI bytes to convert
-     * @param size the size of usbMidiBytes
-     * @return byte array of raw MIDI packets
+     * createEncoders() must be called before raw MIDI can be converted to USB MIDI.
+     *
+     * @param size the number of encoders to create
      */
-    public byte[] usbMidiToRawMidi(byte[] usbMidiBytes, int size) {
-        return mUsbMidiDecoder.decode(usbMidiBytes, size);
+    public void createEncoders(int size) {
+        mUsbMidiEncoders = new UsbMidiEncoder[size];
+        for (int i = 0; i < size; i++) {
+            mUsbMidiEncoders[i] = new UsbMidiEncoder(i);
+        }
     }
 
     /**
      * Converts a raw MIDI array into a USB MIDI array.
      *
+     * Call pullEncodedMidiPackets to retrieve the byte array.
+     *
      * @param midiBytes the raw MIDI bytes to convert
      * @param size the size of usbMidiBytes
      * @param encoderId which encoder to use
+     */
+    public void encodeMidiPackets(byte[] midiBytes, int size, int encoderId) {
+        // Use the first encoder if the encoderId is invalid.
+        if (encoderId >= mUsbMidiEncoders.length) {
+            Log.w(TAG, "encoderId " + encoderId + " invalid");
+            encoderId = 0;
+        }
+        byte[] encodedPacket = mUsbMidiEncoders[encoderId].encode(midiBytes, size);
+        mEncoderOutputStream.write(encodedPacket, 0, encodedPacket.length);
+    }
+
+    /**
+     * Returns the encoded MIDI packets from encodeMidiPackets
+     *
      * @return byte array of USB MIDI packets
      */
-    public byte[] rawMidiToUsbMidi(byte[] midiBytes, int size, int encoderId) {
-        return mUsbMidiEncoders[encoderId].encode(midiBytes, size);
+    public byte[] pullEncodedMidiPackets() {
+        byte[] output = mEncoderOutputStream.toByteArray();
+        mEncoderOutputStream.reset();
+        return output;
+    }
+
+    /**
+     * Creates decoders.
+     *
+     * createDecoders() must be called before USB MIDI can be converted to raw MIDI.
+     *
+     * @param size the number of decoders to create
+     */
+    public void createDecoders(int size) {
+        mUsbMidiDecoder = new UsbMidiDecoder(size);
+    }
+
+    /**
+     * Converts a USB MIDI array into a multiple MIDI arrays, one per cable.
+     *
+     * Call pullDecodedMidiPackets to retrieve the byte array.
+     *
+     * @param usbMidiBytes the USB MIDI bytes to convert
+     * @param size the size of usbMidiBytes
+     */
+    public void decodeMidiPackets(byte[] usbMidiBytes, int size) {
+        mUsbMidiDecoder.decode(usbMidiBytes, size);
+    }
+
+    /**
+     * Returns the decoded MIDI packets from decodeMidiPackets
+     *
+     * @param cableNumber the cable to pull data from
+     * @return byte array of raw MIDI packets
+     */
+    public byte[] pullDecodedMidiPackets(int cableNumber) {
+        return mUsbMidiDecoder.pullBytes(cableNumber);
     }
 
     private class UsbMidiDecoder {
+        int mNumJacks;
+        ByteArrayOutputStream[] mDecodedByteArrays;
+
+        UsbMidiDecoder(int numJacks) {
+            mNumJacks = numJacks;
+            mDecodedByteArrays = new ByteArrayOutputStream[numJacks];
+            for (int i = 0; i < numJacks; i++) {
+                mDecodedByteArrays[i] = new ByteArrayOutputStream();
+            }
+        }
+
         // Decodes the data from USB MIDI to raw MIDI.
         // Each valid 4 byte input maps to a 1-3 byte output.
         // Reference the USB MIDI 1.0 spec for more info.
-        public byte[] decode(byte[] usbMidiBytes, int size) {
+        public void decode(byte[] usbMidiBytes, int size) {
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+            if (size % 4 != 0) {
+                Log.w(TAG, "size " + size + " not multiple of 4");
+            }
             for (int i = 0; i + 3 < size; i += 4) {
+                int cableNumber = (usbMidiBytes[i] >> 4) & 0x0f;
                 int codeIndex = usbMidiBytes[i] & 0x0f;
                 int numPayloadBytes = PAYLOAD_SIZE[codeIndex];
                 if (numPayloadBytes < 0) {
                     continue;
                 }
-                outputStream.write(usbMidiBytes, i + 1, numPayloadBytes);
+                // Use the first cable if the cable number is invalid.
+                if (cableNumber >= mNumJacks) {
+                    Log.w(TAG, "cableNumber " + cableNumber + " invalid");
+                    cableNumber = 0;
+                }
+                mDecodedByteArrays[cableNumber].write(usbMidiBytes, i + 1, numPayloadBytes);
             }
-            return outputStream.toByteArray();
+        }
+
+        public byte[] pullBytes(int cableNumber) {
+            // Use the first cable if the cable number is invalid.
+            if (cableNumber >= mNumJacks) {
+                Log.w(TAG, "cableNumber " + cableNumber + " invalid");
+                cableNumber = 0;
+            }
+            byte[] output = mDecodedByteArrays[cableNumber].toByteArray();
+            mDecodedByteArrays[cableNumber].reset();
+            return output;
         }
     }
 
@@ -135,6 +219,13 @@
 
         private byte[] mEmptyBytes = new byte[3]; // Used to fill out extra data
 
+        private byte mShiftedCableNumber;
+
+        UsbMidiEncoder(int cableNumber) {
+            // Jack Id is always the left nibble of every byte so shift this now.
+            mShiftedCableNumber = (byte) (cableNumber << 4);
+        }
+
         // Encodes the data from raw MIDI to USB MIDI.
         // Each valid 1-3 byte input maps to a 4 byte output.
         // Reference the USB MIDI 1.0 spec for more info.
@@ -153,7 +244,8 @@
                                 midiBytes[curLocation];
                         mNumStoredSystemExclusiveBytes++;
                         if (mNumStoredSystemExclusiveBytes == 3) {
-                            outputStream.write(CODE_INDEX_NUMBER_SYSEX_STARTS_OR_CONTINUES);
+                            outputStream.write(CODE_INDEX_NUMBER_SYSEX_STARTS_OR_CONTINUES
+                                    | mShiftedCableNumber);
                             outputStream.write(mStoredSystemExclusiveBytes, 0, 3);
                             mNumStoredSystemExclusiveBytes = 0;
                         }
@@ -179,7 +271,7 @@
                     byte codeIndexNumber = (byte) ((midiBytes[curLocation] >> 4) & 0x0f);
                     int channelMessageSize = PAYLOAD_SIZE[codeIndexNumber];
                     if (curLocation + channelMessageSize <= size) {
-                        outputStream.write(codeIndexNumber);
+                        outputStream.write(codeIndexNumber | mShiftedCableNumber);
                         outputStream.write(midiBytes, curLocation, channelMessageSize);
                         // Fill in the rest of the bytes with 0.
                         outputStream.write(mEmptyBytes, 0, 3 - channelMessageSize);
@@ -197,8 +289,8 @@
                     curLocation++;
                 } else if (midiBytes[curLocation] == SYSEX_END_EXCLUSIVE) {
                     // 1 byte is 0x05, 2 bytes is 0x06, and 3 bytes is 0x07
-                    outputStream.write(CODE_INDEX_NUMBER_SYSEX_END_SINGLE_BYTE
-                            + mNumStoredSystemExclusiveBytes);
+                    outputStream.write((CODE_INDEX_NUMBER_SYSEX_END_SINGLE_BYTE
+                            + mNumStoredSystemExclusiveBytes) | mShiftedCableNumber);
                     mStoredSystemExclusiveBytes[mNumStoredSystemExclusiveBytes] =
                             midiBytes[curLocation];
                     mNumStoredSystemExclusiveBytes++;
@@ -218,7 +310,7 @@
                     } else {
                         int systemMessageSize = PAYLOAD_SIZE[codeIndexNumber];
                         if (curLocation + systemMessageSize <= size) {
-                            outputStream.write(codeIndexNumber);
+                            outputStream.write(codeIndexNumber | mShiftedCableNumber);
                             outputStream.write(midiBytes, curLocation, systemMessageSize);
                             // Fill in the rest of the bytes with 0.
                             outputStream.write(mEmptyBytes, 0, 3 - systemMessageSize);
@@ -236,7 +328,7 @@
         }
 
         private void writeSingleByte(ByteArrayOutputStream outputStream, byte byteToWrite) {
-            outputStream.write(CODE_INDEX_NUMBER_SINGLE_BYTE);
+            outputStream.write(CODE_INDEX_NUMBER_SINGLE_BYTE | mShiftedCableNumber);
             outputStream.write(byteToWrite);
             outputStream.write(0);
             outputStream.write(0);
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
index 1f448ac..117a3d9 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbEndpointDescriptor.java
@@ -118,7 +118,7 @@
         mClassSpecificEndpointDescriptor = descriptor;
     }
 
-    UsbDescriptor getClassSpecificEndpointDescriptor() {
+    public UsbDescriptor getClassSpecificEndpointDescriptor() {
         return mClassSpecificEndpointDescriptor;
     }
 
diff --git a/services/voiceinteraction/TEST_MAPPING b/services/voiceinteraction/TEST_MAPPING
index d6c6964..5fe1c8d 100644
--- a/services/voiceinteraction/TEST_MAPPING
+++ b/services/voiceinteraction/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "presubmit-large": [
+  "presubmit": [
     {
       "name": "CtsVoiceInteractionTestCases",
       "options": [
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
index ce1157e..7d5750e 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewareLogging.java
@@ -30,11 +30,14 @@
 import android.media.soundtrigger_middleware.ISoundTriggerCallback;
 import android.media.soundtrigger_middleware.ISoundTriggerModule;
 import android.media.soundtrigger_middleware.SoundTriggerModuleDescriptor;
+import android.os.BatteryStatsInternal;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.util.Log;
 
 import com.android.internal.util.LatencyTracker;
+import com.android.server.LocalServices;
 
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
@@ -291,6 +294,8 @@
             public void onRecognition(int modelHandle, RecognitionEvent event, int captureSession)
                     throws RemoteException {
                 try {
+                    BatteryStatsHolder.INSTANCE.noteWakingSoundTrigger(
+                            SystemClock.elapsedRealtime(), mOriginatorIdentity.uid);
                     mCallbackDelegate.onRecognition(modelHandle, event, captureSession);
                     logVoidReturn("onRecognition", modelHandle, event);
                 } catch (Exception e) {
@@ -304,6 +309,8 @@
                     int captureSession)
                     throws RemoteException {
                 try {
+                    BatteryStatsHolder.INSTANCE.noteWakingSoundTrigger(
+                            SystemClock.elapsedRealtime(), mOriginatorIdentity.uid);
                     startKeyphraseEventLatencyTracking(event);
                     mCallbackDelegate.onPhraseRecognition(modelHandle, event, captureSession);
                     logVoidReturn("onPhraseRecognition", modelHandle, event);
@@ -387,6 +394,12 @@
         }
     }
 
+    private static class BatteryStatsHolder {
+        private static final BatteryStatsInternal INSTANCE =
+                LocalServices.getService(BatteryStatsInternal.class);
+    }
+
+
     ////////////////////////////////////////////////////////////////////////////////////////////////
     // Actual logging logic below.
     private static final int NUM_EVENTS_TO_DUMP = 64;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index de99ebf..9170117 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -2073,6 +2073,14 @@
      * {@link #getPhoneAccount}. Self-managed {@link ConnectionService}s must have
      * {@link android.Manifest.permission#MANAGE_OWN_CALLS} to add a new incoming call.
      * <p>
+     * Specify the address associated with the incoming call using
+     * {@link #EXTRA_INCOMING_CALL_ADDRESS}.  If an incoming call is from an anonymous source, omit
+     * this extra and ensure you specify a valid number presentation via
+     * {@link Connection#setAddress(Uri, int)} on the {@link Connection} instance you return in
+     * your
+     * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}
+     * implementation.
+     * <p>
      * The incoming call you are adding is assumed to have a video state of
      * {@link VideoProfile#STATE_AUDIO_ONLY}, unless the extra value
      * {@link #EXTRA_INCOMING_VIDEO_STATE} is specified.
diff --git a/telephony/java/android/telephony/DomainSelectionService.java b/telephony/java/android/telephony/DomainSelectionService.java
index c352f2b..abcce5f 100644
--- a/telephony/java/android/telephony/DomainSelectionService.java
+++ b/telephony/java/android/telephony/DomainSelectionService.java
@@ -537,9 +537,9 @@
         }
 
         @Override
-        public void onWlanSelected() {
+        public void onWlanSelected(boolean useEmergencyPdn) {
             try {
-                mCallback.onWlanSelected();
+                mCallback.onWlanSelected(useEmergencyPdn);
             } catch (Exception e) {
                 Rlog.e(TAG, "onWlanSelected e=" + e);
             }
@@ -702,9 +702,10 @@
         }
 
         @Override
-        public void onDomainSelected(@NetworkRegistrationInfo.Domain int domain) {
+        public void onDomainSelected(@NetworkRegistrationInfo.Domain int domain,
+                boolean useEmergencyPdn) {
             try {
-                mCallback.onDomainSelected(domain);
+                mCallback.onDomainSelected(domain, useEmergencyPdn);
             } catch (Exception e) {
                 Rlog.e(TAG, "onDomainSelected e=" + e);
             }
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index b9008c4..788d0e8 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1526,7 +1526,7 @@
      * Formats the specified {@code phoneNumber} to the E.164 representation.
      *
      * @param phoneNumber the phone number to format.
-     * @param defaultCountryIso the ISO 3166-1 two letters country code.
+     * @param defaultCountryIso the ISO 3166-1 two letters country code in UPPER CASE.
      * @return the E.164 representation, or null if the given phone number is not valid.
      */
     public static String formatNumberToE164(String phoneNumber, String defaultCountryIso) {
@@ -1537,7 +1537,7 @@
      * Formats the specified {@code phoneNumber} to the RFC3966 representation.
      *
      * @param phoneNumber the phone number to format.
-     * @param defaultCountryIso the ISO 3166-1 two letters country code.
+     * @param defaultCountryIso the ISO 3166-1 two letters country code in UPPER CASE.
      * @return the RFC3966 representation, or null if the given phone number is not valid.
      */
     public static String formatNumberToRFC3966(String phoneNumber, String defaultCountryIso) {
diff --git a/telephony/java/android/telephony/TransportSelectorCallback.java b/telephony/java/android/telephony/TransportSelectorCallback.java
index d396790..04752e4 100644
--- a/telephony/java/android/telephony/TransportSelectorCallback.java
+++ b/telephony/java/android/telephony/TransportSelectorCallback.java
@@ -35,8 +35,10 @@
 
     /**
      * Notify that WLAN transport has been selected.
+     *
+     * @param useEmergencyPdn Indicates whether Wi-Fi emergency services use emergency PDN or not.
      */
-    void onWlanSelected();
+    void onWlanSelected(boolean useEmergencyPdn);
 
     /**
      * Notify that WWAN transport has been selected.
diff --git a/telephony/java/android/telephony/WwanSelectorCallback.java b/telephony/java/android/telephony/WwanSelectorCallback.java
index b3682ca..f9c2620 100644
--- a/telephony/java/android/telephony/WwanSelectorCallback.java
+++ b/telephony/java/android/telephony/WwanSelectorCallback.java
@@ -46,6 +46,7 @@
      * this interface can be discarded.
      *
      * @param domain The selected domain.
+     * @param useEmergencyPdn Indicates whether emergency services use emergency PDN or not.
      */
-    void onDomainSelected(@NetworkRegistrationInfo.Domain int domain);
+    void onDomainSelected(@NetworkRegistrationInfo.Domain int domain, boolean useEmergencyPdn);
 }
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index 98ed1fa..ecd7039 100755
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -584,6 +584,7 @@
      * Gets the call ID of the session.
      *
      * @return the call ID
+     * If null is returned for getCallId, then that means that the call ID has not been set yet.
      */
     public String getCallId() {
         if (mClosed) {
@@ -1779,7 +1780,7 @@
         sb.append("[ImsCallSession objId:");
         sb.append(System.identityHashCode(this));
         sb.append(" callId:");
-        sb.append(getCallId());
+        sb.append(mCallId != null ? mCallId : "[UNINITIALIZED]");
         sb.append("]");
         return sb.toString();
     }
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index f8cf81c..64454cc 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -166,8 +166,8 @@
     public static final String KEY_SATELLITE_NEXT_VISIBILITY = "satellite_next_visibility";
 
     /**
-     * Bundle key to get the respoonse from
-     * {@link #sendSatelliteDatagram(long, int, SatelliteDatagram, Executor, OutcomeReceiver)}.
+     * Bundle key to get the respoonse from {@link
+     * #sendSatelliteDatagram(long, int, SatelliteDatagram, boolean, Executor, OutcomeReceiver)}.
      * @hide
      */
     public static final String KEY_SEND_SATELLITE_DATAGRAM = "send_satellite_datagram";
@@ -615,9 +615,7 @@
 
     /**
      * The default state indicating that datagram transfer is idle.
-     * This should be sent immediately after either
-     * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_SUCCESS} or
-     * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED}.
+     * This should be sent if there are no message transfer activity happening.
      */
     public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE = 0;
     /**
@@ -625,25 +623,41 @@
      */
     public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING = 1;
     /**
+     * An end state indicating that datagram sending completed successfully.
+     * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
+     * will be sent if no more messages are pending.
+     */
+    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS = 2;
+    /**
+     * An end state indicating that datagram sending completed with a failure.
+     * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
+     * must be sent before reporting any additional datagram transfer state changes. All pending
+     * messages will be reported as failed, to the corresponding applications.
+     */
+    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED = 3;
+    /**
      * A transition state indicating that a datagram is being received.
      */
-    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING = 2;
+    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING = 4;
     /**
-     * A transition state indicating that datagram transfer is being retried.
-     */
-    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RETRYING = 3;
-    /**
-     * An end state indicating that datagram transfer completed successfully.
+     * An end state indicating that datagram receiving completed successfully.
      * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
-     * must be sent before reporting any additional datagram transfer state changes.
+     * will be sent if no more messages are pending.
      */
-    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_SUCCESS = 4;
+    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS = 5;
     /**
-     * An end state indicating that datagram transfer completed with a failure.
+     * An end state indicating that datagram receive operation found that there are no
+     * messages to be retrieved from the satellite.
      * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
-     * must be sent before reporting any additional datagram transfer state changes.
+     * will be sent if no more messages are pending.
      */
-    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED = 5;
+    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE = 6;
+    /**
+     * An end state indicating that datagram receive completed with a failure.
+     * After datagram transfer completes, {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE}
+     * will be sent if no more messages are pending.
+     */
+    public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED = 7;
     /**
      * The datagram transfer state is unknown. This generic datagram transfer state should be used
      * only when the datagram transfer state cannot be mapped to other specific datagram transfer
@@ -655,10 +669,12 @@
     @IntDef(prefix = {"SATELLITE_DATAGRAM_TRANSFER_STATE_"}, value = {
             SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
             SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
+            SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
+            SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
             SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
-            SATELLITE_DATAGRAM_TRANSFER_STATE_RETRYING,
-            SATELLITE_DATAGRAM_TRANSFER_STATE_SUCCESS,
-            SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED,
+            SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS,
+            SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE,
+            SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
             SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -685,6 +701,10 @@
      */
     public static final int SATELLITE_MODEM_STATE_OFF = 4;
     /**
+     * Satellite modem is unavailable.
+     */
+    public static final int SATELLITE_MODEM_STATE_UNAVAILABLE = 5;
+    /**
      * Satellite modem state is unknown. This generic modem state should be used only when the
      * modem state cannot be mapped to other specific modem states.
      */
@@ -697,6 +717,7 @@
             SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING,
             SATELLITE_MODEM_STATE_DATAGRAM_RETRYING,
             SATELLITE_MODEM_STATE_OFF,
+            SATELLITE_MODEM_STATE_UNAVAILABLE,
             SATELLITE_MODEM_STATE_UNKNOWN
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -733,9 +754,6 @@
      * All other results indicate that this operation failed.
      * Once satellite position updates begin, datagram transfer state updates will be sent
      * through {@link SatellitePositionUpdateCallback}.
-     * Modem should report any changes in datagram transfer state and indicate success or failure
-     * by reporting {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_SUCCESS} or
-     * {@link #SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED}.
      *
      * @param executor The executor on which the callback and error code listener will be called.
      * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index 5dc1a65..d93ee21 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -31,7 +31,6 @@
      * Register the callback interface with satellite service.
      *
      * @param listener The callback interface to handle satellite service indications.
-     * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -43,7 +42,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void setSatelliteListener(in ISatelliteListener listener, in IIntegerConsumer errorCallback);
+    void setSatelliteListener(in ISatelliteListener listener);
 
     /**
      * Request to enable or disable the satellite service listening mode.
@@ -51,6 +50,8 @@
      *
      * @param enable True to enable satellite listening mode and false to disable.
      * @param isDemoMode Whether demo mode is enabled.
+     * @param timeout How long the satellite modem should wait for the next incoming page before
+     *                disabling listening mode.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
@@ -63,7 +64,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    void requestSatelliteListeningEnabled(in boolean enable, in boolean isDemoMode,
+    void requestSatelliteListeningEnabled(in boolean enable, in boolean isDemoMode, in int timeout,
             in IIntegerConsumer errorCallback);
 
     /**
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
index e24e892e..d966868 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
@@ -36,10 +36,10 @@
     /**
      * Indicates that new datagrams have been received on the device.
      *
-     * @param datagrams Array of new datagrams received.
-     * @param pendingCount The number of datagrams that are pending.
+     * @param datagram New datagram that was received.
+     * @param pendingCount Number of additional datagrams yet to be received.
      */
-    void onSatelliteDatagramsReceived(in SatelliteDatagram[] datagrams, in int pendingCount);
+    void onSatelliteDatagramReceived(in SatelliteDatagram datagram, in int pendingCount);
 
     /**
      * Indicates that the satellite has pending datagrams for the device to be pulled.
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
index df51432..711dcbe 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -63,19 +63,19 @@
 
     private final IBinder mBinder = new ISatellite.Stub() {
         @Override
-        public void setSatelliteListener(ISatelliteListener listener,
-                IIntegerConsumer errorCallback) throws RemoteException {
+        public void setSatelliteListener(ISatelliteListener listener) throws RemoteException {
             executeMethodAsync(
-                    () -> SatelliteImplBase.this.setSatelliteListener(listener, errorCallback),
+                    () -> SatelliteImplBase.this.setSatelliteListener(listener),
                     "setSatelliteListener");
         }
 
         @Override
         public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode,
-                IIntegerConsumer errorCallback) throws RemoteException {
+                int timeout, IIntegerConsumer errorCallback) throws RemoteException {
             executeMethodAsync(
                     () -> SatelliteImplBase.this
-                            .requestSatelliteListeningEnabled(enable, isDemoMode, errorCallback),
+                            .requestSatelliteListeningEnabled(
+                                    enable, isDemoMode, timeout, errorCallback),
                     "requestSatelliteListeningEnabled");
         }
 
@@ -229,7 +229,6 @@
      * Register the callback interface with satellite service.
      *
      * @param listener The callback interface to handle satellite service indications.
-     * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
      *   SatelliteError:ERROR_NONE
@@ -241,8 +240,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    public void setSatelliteListener(@NonNull ISatelliteListener listener,
-            @NonNull IIntegerConsumer errorCallback) {
+    public void setSatelliteListener(@NonNull ISatelliteListener listener) {
         // stub implementation
     }
 
@@ -252,6 +250,8 @@
      *
      * @param enable True to enable satellite listening mode and false to disable.
      * @param isDemoMode Whether demo mode is enabled.
+     * @param timeout How long the satellite modem should wait for the next incoming page before
+     *                disabling listening mode.
      * @param errorCallback The callback to receive the error code result of the operation.
      *
      * Valid error codes returned:
@@ -264,7 +264,7 @@
      *   SatelliteError:REQUEST_NOT_SUPPORTED
      *   SatelliteError:NO_RESOURCES
      */
-    public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode,
+    public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode, int timeout,
             @NonNull IIntegerConsumer errorCallback) {
         // stub implementation
     }
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
index 5ee7f9a..e4f9413 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
@@ -42,6 +42,10 @@
      */
     SATELLITE_MODEM_STATE_OFF = 4,
     /**
+     * Satellite modem is unavailable.
+     */
+    SATELLITE_MODEM_STATE_UNAVAILABLE = 5,
+    /**
      * Satellite modem state is unknown. This generic modem state should be used only when the
      * modem state cannot be mapped to other specific modem states.
      */
diff --git a/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl b/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
index aca83f4..6777256d 100644
--- a/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
+++ b/telephony/java/com/android/internal/telephony/ITransportSelectorCallback.aidl
@@ -22,7 +22,7 @@
 
 interface ITransportSelectorCallback {
     oneway void onCreated(in IDomainSelector selector);
-    oneway void onWlanSelected();
+    oneway void onWlanSelected(boolean useEmergencyPdn);
     IWwanSelectorCallback onWwanSelected();
     oneway void onWwanSelectedAsync(in ITransportSelectorResultCallback cb);
     oneway void onSelectionTerminated(int cause);
diff --git a/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl b/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
index 339fbee..94e7c87 100644
--- a/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
+++ b/telephony/java/com/android/internal/telephony/IWwanSelectorCallback.aidl
@@ -21,6 +21,6 @@
 oneway interface IWwanSelectorCallback {
     void onRequestEmergencyNetworkScan(in int[] preferredNetworks,
             int scanType, in IWwanSelectorResultCallback cb);
-    void onDomainSelected(int domain);
+    void onDomainSelected(int domain, boolean useEmergencyPdn);
     void onCancel();
 }
diff --git a/test-mock/api/current.txt b/test-mock/api/current.txt
index c5169e5..d1a68d4 100644
--- a/test-mock/api/current.txt
+++ b/test-mock/api/current.txt
@@ -235,7 +235,6 @@
     method @Deprecated public android.content.Intent getLaunchIntentForPackage(String);
     method @Deprecated public android.content.Intent getLeanbackLaunchIntentForPackage(String);
     method @Deprecated public String getNameForUid(int);
-    method @Deprecated public android.content.pm.PackageInfo getPackageArchiveInfo(String, int);
     method @Deprecated public int[] getPackageGids(String) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Deprecated public int[] getPackageGids(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Deprecated public android.content.pm.PackageInfo getPackageInfo(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
diff --git a/tests/EnforcePermission/OWNERS b/tests/EnforcePermission/OWNERS
new file mode 100644
index 0000000..39550a3
--- /dev/null
+++ b/tests/EnforcePermission/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 315013
+tweek@google.com
+brufino@google.com
diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp
index 855d3c1..fef5211 100644
--- a/tests/FlickerTests/Android.bp
+++ b/tests/FlickerTests/Android.bp
@@ -42,6 +42,8 @@
         "androidx.test.ext.junit",
         "flickertestapplib",
         "flickerlib",
+        "flickerlib-apphelpers",
+        "flickerlib-helpers",
         "truth-prebuilt",
         "launcher-helper-lib",
         "launcher-aosp-tapl",
@@ -65,6 +67,7 @@
     ],
     static_libs: [
         "flickerlib",
+        "flickerlib-helpers",
         "truth-prebuilt",
         "app-helpers-core",
     ],
@@ -80,8 +83,10 @@
         "**/helpers/*",
     ],
     static_libs: [
-        "flickerlib",
         "flickertestapplib",
+        "flickerlib",
+        "flickerlib-apphelpers",
+        "flickerlib-helpers",
         "truth-prebuilt",
         "app-helpers-core",
         "wm-flicker-window-extensions",
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
index 707b522..f2ffc19 100644
--- a/tests/FlickerTests/AndroidTest.xml
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -24,7 +24,11 @@
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
         <option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />
+        <option name="run-command" value="settings put system show_touches 1" />
+        <option name="run-command" value="settings put system pointer_location 1" />
         <option name="teardown-command" value="settings delete secure show_ime_with_hard_keyboard" />
+        <option name="teardown-command" value="settings delete system show_touches" />
+        <option name="teardown-command" value="settings delete system pointer_location" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true"/>
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 87bfdeb..4e3ae0c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -18,11 +18,13 @@
 
 import android.app.Instrumentation
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerBuilderProvider
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 import android.util.Log
 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.component.matchers.ComponentNameMatcher
 import org.junit.Assume
 import org.junit.AssumptionViolatedException
 import org.junit.Test
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 e3dc699..9dc4bf0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -18,12 +18,13 @@
 
 package com.android.server.wm.flicker
 
-import com.android.server.wm.flicker.helpers.WindowUtils
-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.component.matchers.IComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
-import com.android.server.wm.traces.common.windowmanager.WindowManagerTrace
+import android.tools.common.PlatformConsts
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.datatypes.component.IComponentNameMatcher
+import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.common.traces.wm.WindowManagerTrace
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.helpers.WindowUtils
 
 /**
  * Checks that [ComponentNameMatcher.STATUS_BAR] window is visible and above the app windows in all
@@ -208,7 +209,7 @@
     wmTrace: WindowManagerTrace? = this.reader.readWmTrace()
 ) {
     // collect navbar position for the equivalent WM state
-    val state = wmTrace?.firstOrNull() ?: error("WM state missing in $this")
+    val state = wmTrace?.entries?.firstOrNull() ?: error("WM state missing in $this")
     val display = state.getDisplay(PlatformConsts.DEFAULT_DISPLAY) ?: error("Display not found")
     val navBarPosition = WindowUtils.getExpectedStatusBarPosition(display)
     assertLayersStart {
@@ -224,7 +225,7 @@
     wmTrace: WindowManagerTrace? = this.reader.readWmTrace()
 ) {
     // collect navbar position for the equivalent WM state
-    val state = wmTrace?.lastOrNull() ?: error("WM state missing in $this")
+    val state = wmTrace?.entries?.lastOrNull() ?: error("WM state missing in $this")
     val display = state.getDisplay(PlatformConsts.DEFAULT_DISPLAY) ?: error("Display not found")
     val navBarPosition = WindowUtils.getExpectedStatusBarPosition(display)
     assertLayersEnd {
@@ -257,7 +258,7 @@
             if (snapshotLayers.isNotEmpty()) {
                 val visibleAreas =
                     snapshotLayers
-                        .mapNotNull { snapshotLayer -> snapshotLayer.layer?.visibleRegion }
+                        .mapNotNull { snapshotLayer -> snapshotLayer.layer.visibleRegion }
                         .toTypedArray()
                 val snapshotRegion = RegionSubject(visibleAreas, this, timestamp)
                 val appVisibleRegion = it.visibleRegion(component)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt
index b7bdeeb7..7ef4d93 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/ActivityEmbeddingTestBase.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.activityembedding
 
+import android.tools.device.flicker.legacy.FlickerTest
 import com.android.server.wm.flicker.BaseTest
-import com.android.server.wm.flicker.FlickerTest
 import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
 import org.junit.Before
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt
index 7f2e057f..ed17059 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplitTest.kt
@@ -17,12 +17,12 @@
 package com.android.server.wm.flicker.activityembedding
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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 org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
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
index 20259a7..c3cbb84 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
@@ -17,13 +17,13 @@
 package com.android.server.wm.flicker.activityembedding
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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
@@ -59,14 +59,12 @@
     @Presubmit
     @Test
     fun mainActivityWindowIsAlwaysVisible() {
-        flicker.assertWm {
-            isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
-        }
+        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.
+     * 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
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index dba588a..5dc2dd7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -17,12 +17,12 @@
 package com.android.server.wm.flicker.close
 
 import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTestCfArm.kt
index 86f52d5..9fa84019 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTestCfArm.kt
@@ -16,10 +16,10 @@
 
 package com.android.server.wm.flicker.close
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index 4d2b86a..b042a14 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -17,12 +17,12 @@
 package com.android.server.wm.flicker.close
 
 import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTestCfArm.kt
index 4707642..136995a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTestCfArm.kt
@@ -16,10 +16,10 @@
 
 package com.android.server.wm.flicker.close
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
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 4d72729..c4628aa 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
@@ -17,14 +17,14 @@
 package com.android.server.wm.flicker.close
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.LAUNCHER
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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.helpers.SimpleAppHelper
-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.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 65d0fa9..e531bc0 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
@@ -17,6 +17,12 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.wm.WindowManagerState.Companion.STATE_RESUMED
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import android.util.Log
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
@@ -24,10 +30,6 @@
 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.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
 import org.junit.Assume.assumeNotNull
 
 class ActivityEmbeddingAppHelper
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 73018a0..afb9fbf 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,8 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
 
 class AppPairsHelper(
     instrumentation: Instrumentation,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt
index 18563ff..7aea05d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AssistantAppHelper.kt
@@ -19,6 +19,7 @@
 import android.app.Instrumentation
 import android.content.ComponentName
 import android.provider.Settings
+import android.tools.device.helpers.FIND_TIMEOUT
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.UiDevice
 import androidx.test.uiautomator.Until
@@ -31,10 +32,10 @@
     val instr: Instrumentation,
     val component: ComponentName = ActivityOptions.ASSISTANT_SERVICE_COMPONENT_NAME,
 ) {
-    protected val uiDevice: UiDevice = UiDevice.getInstance(instr)
-    protected val defaultAssistant: String? =
+    private val uiDevice: UiDevice = UiDevice.getInstance(instr)
+    private val defaultAssistant: String? =
         Settings.Secure.getString(instr.targetContext.contentResolver, Settings.Secure.ASSISTANT)
-    protected val defaultVoiceInteractionService: String? =
+    private val defaultVoiceInteractionService: String? =
         Settings.Secure.getString(
             instr.targetContext.contentResolver,
             Settings.Secure.VOICE_INTERACTION_SERVICE
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 cdf7ae5..47dd4e9 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
@@ -17,9 +17,10 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
 
 class FixedOrientationAppHelper
 @JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
index 2ae8e1d..9227e07 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
@@ -18,16 +18,16 @@
 
 package com.android.server.wm.flicker.helpers
 
-import com.android.server.wm.flicker.IFlickerTestData
-import com.android.server.wm.flicker.rules.ChangeDisplayOrientationRule
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.Rotation
+import android.tools.device.flicker.legacy.IFlickerTestData
+import android.tools.device.flicker.rules.ChangeDisplayOrientationRule
 
 /**
  * Changes the device [rotation] and wait for the rotation animation to complete
  *
  * @param rotation New device rotation
  */
-fun IFlickerTestData.setRotation(rotation: PlatformConsts.Rotation) =
+fun IFlickerTestData.setRotation(rotation: Rotation) =
     ChangeDisplayOrientationRule.setRotation(
         rotation,
         instrumentation,
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 f5aed41..79c048a 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
@@ -17,13 +17,14 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import androidx.test.uiautomator.By
 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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
 class GameAppHelper
 @JvmOverloads
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 a433b15..73effbd 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
@@ -17,12 +17,14 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
 open class ImeAppHelper
 @JvmOverloads
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 fb0242e..a6e57d5 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
@@ -17,12 +17,13 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
 class ImeEditorPopupDialogAppHelper
 @JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
index fb04b32..d61a500 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
@@ -17,26 +17,28 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.common.traces.Condition
+import android.tools.common.traces.DeviceStateDump
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.helpers.IME_PACKAGE
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import android.view.WindowInsets.Type.ime
 import android.view.WindowInsets.Type.navigationBars
 import android.view.WindowInsets.Type.statusBars
 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.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 ImeShownOnAppStartHelper
 @JvmOverloads
 constructor(
     instr: Instrumentation,
-    private val rotation: PlatformConsts.Rotation,
+    private val rotation: Rotation,
     private val imePackageName: String = IME_PACKAGE,
     launcherName: String = ActivityOptions.Ime.AutoFocusActivity.LABEL,
     component: ComponentNameMatcher =
@@ -55,7 +57,12 @@
         waitConditions: Array<Condition<DeviceStateDump>>
     ) {
         super.launchViaIntent(
-            wmHelper, launchedAppComponentMatcherOverride, action, stringExtras, waitConditions)
+            wmHelper,
+            launchedAppComponentMatcherOverride,
+            action,
+            stringExtras,
+            waitConditions
+        )
         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 8a25e36..fb5e1d2 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
@@ -17,9 +17,10 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
 
 class ImeStateInitializeHelper
 @JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt
index ba8dabd..b95d86b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt
@@ -17,8 +17,9 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.parser.toFlickerComponent
 
 class LaunchBubbleHelper(instrumentation: Instrumentation) :
     StandardAppHelper(
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 d6ed24a..ab91685 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
@@ -17,13 +17,15 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.toFlickerComponent
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Direction
 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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
 
 class MailAppHelper
 @JvmOverloads
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 ae42232..e93e9c8 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
@@ -19,9 +19,10 @@
 import android.app.Instrumentation
 import android.content.Context
 import android.provider.Settings
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
 import android.util.Log
 import com.android.compatibility.common.util.SystemUtil
-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 5c1eca3..c547ad0 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
@@ -17,13 +17,15 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import androidx.test.uiautomator.By
 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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
 class NewTasksAppHelper
 @JvmOverloads
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 58da2d8..20ee3b9 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
@@ -17,9 +17,10 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
 
 class NonResizeableAppHelper
 @JvmOverloads
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 d7f0830..78f8bcf 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
@@ -17,12 +17,14 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
 class NotificationAppHelper
 @JvmOverloads
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 0c8589d..0e852b6 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
@@ -19,17 +19,19 @@
 import android.app.Instrumentation
 import android.media.session.MediaController
 import android.media.session.MediaSessionManager
+import android.tools.common.datatypes.Rect
+import android.tools.common.datatypes.Region
+import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.common.traces.ConditionsFactory
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.helpers.SYSTEMUI_PACKAGE
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import android.util.Log
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.helpers.GestureHelper.Tuple
 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
 
 open class PipAppHelper(instrumentation: Instrumentation) :
     StandardAppHelper(
@@ -93,10 +95,10 @@
 
         // if the distance per step is less than 1, carry out the animation in two steps
         gestureHelper.pinch(
-            Tuple(initLeftX, yCoord),
-            Tuple(initRightX, yCoord),
-            Tuple(finalLeftX, yCoord),
-            Tuple(finalRightX, yCoord),
+            GestureHelper.Tuple(initLeftX, yCoord),
+            GestureHelper.Tuple(initRightX, yCoord),
+            GestureHelper.Tuple(finalLeftX, yCoord),
+            GestureHelper.Tuple(finalRightX, yCoord),
             adjustedSteps
         )
 
@@ -141,10 +143,10 @@
 
         // if the distance per step is less than 1, carry out the animation in two steps
         gestureHelper.pinch(
-            Tuple(initLeftX, yCoord),
-            Tuple(initRightX, yCoord),
-            Tuple(finalLeftX, yCoord),
-            Tuple(finalRightX, yCoord),
+            GestureHelper.Tuple(initLeftX, yCoord),
+            GestureHelper.Tuple(initRightX, yCoord),
+            GestureHelper.Tuple(finalLeftX, yCoord),
+            GestureHelper.Tuple(finalRightX, yCoord),
             adjustedSteps
         )
 
@@ -167,7 +169,7 @@
             launchedAppComponentMatcherOverride,
             action,
             stringExtras,
-            waitConditions = arrayOf(WindowManagerConditionsFactory.hasPipWindow())
+            waitConditions = arrayOf(ConditionsFactory.hasPipWindow())
         )
 
         wmHelper.StateSyncBuilder().withPipShown().waitForAndVerify()
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 8f54000..06e668e 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
@@ -17,9 +17,10 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
 
 class SeamlessRotationAppHelper
 @JvmOverloads
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 61dabfc..94c90da 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
@@ -17,9 +17,10 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
 
 class ShowWhenLockedAppHelper
 @JvmOverloads
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 9ed9d28e..64af811 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
@@ -17,9 +17,10 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import com.android.server.wm.flicker.testapp.ActivityOptions
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
 
 class SimpleAppHelper
 @JvmOverloads
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 8f7049a..316766a 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
@@ -17,13 +17,15 @@
 package com.android.server.wm.flicker.helpers
 
 import android.app.Instrumentation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.helpers.FIND_TIMEOUT
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
 import androidx.test.uiautomator.By
 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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.parser.toFlickerComponent
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 
 class TwoActivitiesAppHelper
 @JvmOverloads
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
index 092a4fd..c23cf34 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
@@ -17,16 +17,16 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.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.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
@@ -86,9 +86,7 @@
                 if (imeSnapshotLayers.isNotEmpty()) {
                     val visibleAreas =
                         imeSnapshotLayers
-                            .mapNotNull { imeSnapshotLayer ->
-                                imeSnapshotLayer.layer?.visibleRegion
-                            }
+                            .mapNotNull { imeSnapshotLayer -> imeSnapshotLayer.layer.visibleRegion }
                             .toTypedArray()
                     val imeVisibleRegion = RegionSubject(visibleAreas, this, timestamp)
                     val appVisibleRegion = it.visibleRegion(imeTestApp)
@@ -105,7 +103,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
index 0870cec..823328a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
@@ -18,15 +18,15 @@
 
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.ImeAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-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
@@ -117,7 +117,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt
index 96b23bc..0fe52df 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.ime
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
index 48dbf25..a4e4b6f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
@@ -17,15 +17,15 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.junit.FlickerParametersRunnerFactory
-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
@@ -96,7 +96,7 @@
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
                 // b/190352379 (IME doesn't show on app launch in 90 degrees)
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt
index ed5d309..5aacb30 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.ime
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
index 7b935ff..e85da1f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
@@ -17,15 +17,15 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.junit.FlickerParametersRunnerFactory
-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
@@ -90,7 +90,7 @@
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
                 // b/190352379 (IME doesn't show on app launch in 90 degrees)
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt
index 0a89991..eb81aed 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.ime
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
index 1a0c959..1b4d6ad 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
@@ -19,15 +19,15 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.ImeAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt
index 37e8c6b..db1440b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.ime
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
index 0b7b165..e2d6dbf 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTest.kt
@@ -19,16 +19,16 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.ImeAppHelper
 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.service.PlatformConsts
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -93,7 +93,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt
index 116bc1b..405ab6b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToHomeOnFinishActivityTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.ime
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
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 dcffa47..579c10f 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
@@ -18,8 +18,8 @@
 
 package com.android.server.wm.flicker.ime
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerTest
 
 fun FlickerTest.imeLayerBecomesVisible() {
     assertLayers {
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
index defb437..3a8db45 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
@@ -16,17 +16,18 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.Postsubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
 import 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
@@ -107,10 +108,9 @@
             return FlickerTestFactory.nonRotationTests(
                 supportedRotations =
                     listOf(
-                        PlatformConsts.Rotation.ROTATION_90,
+                        Rotation.ROTATION_90,
                     ),
-                supportedNavigationModes =
-                    listOf(PlatformConsts.NavBar.MODE_3BUTTON, PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_3BUTTON, NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
index 89d37db..1fee20d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTest.kt
@@ -18,17 +18,17 @@
 
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.snapshotStartingWindowLayerCoversExactlyOnApp
-import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -64,7 +64,7 @@
         }
         transitions {
             // Bring the existing IME activity to the front in landscape mode device rotation.
-            setRotation(PlatformConsts.Rotation.ROTATION_90)
+            setRotation(Rotation.ROTATION_90)
             imeTestApp.launchViaIntent(wmHelper)
         }
         teardown { imeTestApp.exit(wmHelper) }
@@ -99,7 +99,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_90)
+                supportedRotations = listOf(Rotation.ROTATION_90)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt
index 307821f..3aca2a0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromFixedOrientationTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.ime
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
index c72e4e4..6179fc2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
@@ -17,17 +17,17 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.reopenAppFromOverview
 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.reopenAppFromOverview
 import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-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
@@ -142,7 +142,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
index 167689c..954f589 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
@@ -18,18 +18,19 @@
 
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
 import org.junit.Before
 import org.junit.FixMethodOrder
@@ -133,8 +134,8 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL),
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL),
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt
index 82c38a3..0f57467 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestCfArm.kt
@@ -17,8 +17,8 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
index 6c6003f..a927102 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTestShellTransit.kt
@@ -17,10 +17,10 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.Assume
 import org.junit.Before
 import org.junit.FixMethodOrder
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
index e7cfb9e..7514c9b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
@@ -17,17 +17,17 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.Presubmit
-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 android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
 import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
 import com.android.server.wm.flicker.helpers.ImeStateInitializeHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.BaseTest
 import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-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
@@ -123,7 +123,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
index e7ecb87..194c86b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnStartWhenLaunchingAppCfArmTest.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.ime
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
index 851651e..d133529 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTest.kt
@@ -18,14 +18,14 @@
 
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.ImeAppHelper
-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
@@ -81,7 +81,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt
index 0c53155..f5b2294 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhenFocusingOnInputFieldTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.ime
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
index 6058212..99b9bd2bfc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
@@ -17,18 +17,18 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import android.view.WindowInsets.Type.ime
 import android.view.WindowInsets.Type.navigationBars
 import android.view.WindowInsets.Type.statusBars
 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.junit.FlickerParametersRunnerFactory
-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
 import org.junit.FixMethodOrder
@@ -91,7 +91,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
index 5d96346..9ea12a9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
@@ -17,19 +17,19 @@
 package com.android.server.wm.flicker.ime
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.ConditionsFactory
+import android.tools.device.flicker.isShellTransitionsEnabled
+import com.android.server.wm.flicker.helpers.ImeShownOnAppStartHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.traces.parsers.WindowManagerStateHelper
 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.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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.WindowManagerConditionsFactory
-import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Ignore
@@ -82,7 +82,7 @@
     private fun waitNavStatusBarVisibility(stateSync: WindowManagerStateHelper.StateSyncBuilder) {
         when {
             flicker.scenario.isLandscapeOrSeascapeAtStart && !flicker.scenario.isTablet ->
-                stateSync.add(WindowManagerConditionsFactory.isStatusBarVisible().negate())
+                stateSync.add(ConditionsFactory.isStatusBarVisible().negate())
             else -> stateSync.withNavOrTaskBarVisible().withStatusBarVisible()
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt
index 9308fbb..fc39713 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTestCfArm.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.wm.flicker.ime
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
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 7979cf9b..e8f9aa3 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
@@ -17,16 +17,16 @@
 package com.android.server.wm.flicker.launch
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.traces.parsers.toFlickerComponent
 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.TwoActivitiesAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.testapp.ActivityOptions
-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
 import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt
index 549b929..8b89a8b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTestCfArm.kt
@@ -16,9 +16,9 @@
 
 package com.android.server.wm.flicker.launch
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
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 0942287..549183f 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
@@ -16,12 +16,12 @@
 
 package com.android.server.wm.flicker.launch
 
+import android.tools.device.apphelpers.CameraAppHelper
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.CameraAppHelper
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
index 9d86f8c8..19ecf6a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
@@ -16,13 +16,14 @@
 
 package com.android.server.wm.flicker.launch
 
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
 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.flicker.rules.RemoveAllTasksButHomeRule
-import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -61,7 +62,7 @@
                 if (flicker.scenario.isTablet) {
                     tapl.setExpectedRotation(flicker.scenario.startRotation.value)
                 } else {
-                    tapl.setExpectedRotation(PlatformConsts.Rotation.ROTATION_0.value)
+                    tapl.setExpectedRotation(Rotation.ROTATION_0.value)
                 }
                 RemoveAllTasksButHomeRule.removeAllTasksButHome()
             }
@@ -87,7 +88,7 @@
         fun getParams(): Collection<FlickerTest> {
             // TAPL fails on landscape mode b/240916028
             return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_3BUTTON)
+                supportedNavigationModes = listOf(NavBar.MODE_3BUTTON)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index 9fbec97..8fdbb64 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -17,14 +17,14 @@
 package com.android.server.wm.flicker.launch
 
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.annotation.FlickerServiceCompatible
 import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
 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/OpenAppFromLauncherTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
index 2f0e56f..1a1d403 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
@@ -17,9 +17,9 @@
 package com.android.server.wm.flicker.launch
 
 import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerTest
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerTest
 import com.android.server.wm.flicker.replacesLayer
-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 fb6fb22..63ffee6 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
@@ -21,12 +21,12 @@
 import android.platform.test.annotations.Presubmit
 import android.platform.test.rule.SettingOverrideRule
 import android.provider.Settings
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.component.matchers.ComponentNameMatcher
 import org.junit.ClassRule
 import org.junit.FixMethodOrder
 import org.junit.Ignore
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 32276d6..a221ef6 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
@@ -20,13 +20,13 @@
 import android.platform.test.annotations.Presubmit
 import android.platform.test.rule.SettingOverrideRule
 import android.provider.Settings
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.flicker.statusBarLayerPositionAtEnd
-import com.android.server.wm.traces.common.component.matchers.ComponentNameMatcher
 import org.junit.ClassRule
 import org.junit.FixMethodOrder
 import org.junit.Ignore
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 ff39611..4efee55 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
@@ -19,14 +19,14 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
 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.ShowWhenLockedAppHelper
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-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
@@ -46,8 +46,7 @@
 @Postsubmit
 class OpenAppFromLockNotificationWithLockOverlayApp(flicker: FlickerTest) :
     OpenAppFromLockNotificationCold(flicker) {
-    private val showWhenLockedApp: ShowWhenLockedAppHelper =
-        ShowWhenLockedAppHelper(instrumentation)
+    private val showWhenLockedApp = ShowWhenLockedAppHelper(instrumentation)
 
     // Although we are technically still locked here, the overlay app means we should open the
     // notification shade as if we were unlocked.
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 aa054a9..730f78f 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
@@ -18,11 +18,11 @@
 
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
-import com.android.server.wm.flicker.FlickerBuilder
-import com.android.server.wm.flicker.FlickerTest
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 import com.android.server.wm.flicker.navBarLayerPositionAtEnd
 import com.android.server.wm.flicker.statusBarLayerPositionAtEnd
-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 0ed3bba..9c16b79 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
@@ -18,13 +18,13 @@
 
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.flicker.statusBarLayerPositionAtEnd
-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 af6c81d..4a9507a 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
@@ -18,24 +18,24 @@
 
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
 import android.view.WindowInsets
 import android.view.WindowManager
 import androidx.test.filters.RequiresDevice
 import androidx.test.uiautomator.By
 import androidx.test.uiautomator.Until
-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.NotificationAppHelper
 import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.navBarLayerIsVisibleAtEnd
 import com.android.server.wm.flicker.navBarLayerPositionAtEnd
 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.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/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 2b16ef0..00d7544 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -18,14 +18,14 @@
 
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.Rotation
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.annotation.FlickerServiceCompatible
 import com.android.server.wm.flicker.helpers.setRotation
-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
@@ -74,7 +74,7 @@
                 if (flicker.scenario.isTablet) {
                     tapl.setExpectedRotation(flicker.scenario.startRotation.value)
                 } else {
-                    tapl.setExpectedRotation(PlatformConsts.Rotation.ROTATION_0.value)
+                    tapl.setExpectedRotation(Rotation.ROTATION_0.value)
                 }
                 tapl.workspace.switchToOverview()
                 wmHelper.StateSyncBuilder().withRecentsActivityVisible().waitForAndVerify()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTestCfArm.kt
index 1c979e8..ff24190 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTestCfArm.kt
@@ -16,10 +16,10 @@
 
 package com.android.server.wm.flicker.launch
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
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 55e7a99..9ab6156 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
@@ -19,14 +19,15 @@
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
 import org.junit.FixMethodOrder
 import org.junit.Ignore
@@ -213,8 +214,8 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL),
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL),
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
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 618fb8a..e0db96f 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
@@ -17,14 +17,14 @@
 package com.android.server.wm.flicker.launch
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
 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.helpers.SimpleAppHelper
-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.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/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index 93bf099..cdd2d45 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -18,13 +18,13 @@
 
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.annotation.FlickerServiceCompatible
 import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 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/OpenCameraOnDoubleClickPowerButton.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
index 8d2af38..6005a81 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenCameraOnDoubleClickPowerButton.kt
@@ -17,16 +17,16 @@
 package com.android.server.wm.flicker.launch
 
 import android.platform.test.annotations.Postsubmit
+import android.tools.device.apphelpers.CameraAppHelper
+import android.tools.device.flicker.annotation.FlickerServiceCompatible
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import android.view.KeyEvent
 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.annotation.FlickerServiceCompatible
-import com.android.server.wm.flicker.helpers.CameraAppHelper
 import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
 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/OverrideTaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
index c78d0e9..da98523 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
@@ -20,21 +20,20 @@
 import android.os.Bundle
 import android.os.Handler
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.ConditionsFactory
+import android.tools.device.flicker.junit.FlickerBuilderProvider
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
-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.R
-import com.android.server.wm.flicker.helpers.SimpleAppHelper
-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.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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.WindowManagerConditionsFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -58,7 +57,7 @@
 class OverrideTaskTransitionTest(val flicker: FlickerTest) {
 
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
-    private val testApp: StandardAppHelper = SimpleAppHelper(instrumentation)
+    private val testApp = SimpleAppHelper(instrumentation)
 
     @FlickerBuilderProvider
     fun buildFlicker(): FlickerBuilder {
@@ -75,7 +74,7 @@
                 )
                 wmHelper
                     .StateSyncBuilder()
-                    .add(WindowManagerConditionsFactory.isWMStateComplete())
+                    .add(ConditionsFactory.isWMStateComplete())
                     .withAppTransitionIdle()
                     .withWindowSurfaceAppeared(testApp)
                     .waitForAndVerify()
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 94afd81..dd9e4cf 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
@@ -21,23 +21,23 @@
 import android.content.res.Resources
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.DEFAULT_TASK_DISPLAY_AREA
+import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.SPLASH_SCREEN
+import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
+import android.tools.common.datatypes.component.ComponentSplashScreenMatcher
+import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.helpers.WindowUtils
+import android.tools.device.traces.parsers.toFlickerComponent
 import androidx.test.filters.RequiresDevice
 import 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.NewTasksAppHelper
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
-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.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
 import org.junit.Test
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 b7faf83..78cee3c 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
@@ -17,18 +17,18 @@
 package com.android.server.wm.flicker.quickswitch
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.datatypes.Rect
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.NonResizeableAppHelper
 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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.Rect
-import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
 import org.junit.Before
 import org.junit.FixMethodOrder
@@ -237,7 +237,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt
index e6cdd1e..f970a79 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTestCfArm.kt
@@ -16,11 +16,10 @@
 
 package com.android.server.wm.flicker.quickswitch
 
-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.Rect
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.NavBar
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -32,13 +31,11 @@
 class QuickSwitchBetweenTwoAppsBackTestCfArm(flicker: FlickerTest) :
     QuickSwitchBetweenTwoAppsBackTest(flicker) {
     companion object {
-        private var startDisplayBounds = Rect.EMPTY
-
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
index 25d9753..2b69e9b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
@@ -17,10 +17,10 @@
 package com.android.server.wm.flicker.quickswitch
 
 import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.Assume
 import org.junit.Before
 import org.junit.FixMethodOrder
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 6294761..cd7d6fa 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
@@ -17,18 +17,18 @@
 package com.android.server.wm.flicker.quickswitch
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.datatypes.Rect
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.NonResizeableAppHelper
 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.component.matchers.ComponentNameMatcher
-import com.android.server.wm.traces.common.Rect
-import com.android.server.wm.traces.common.service.PlatformConsts
 import org.junit.Assume
 import org.junit.Before
 import org.junit.FixMethodOrder
@@ -255,7 +255,7 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt
index aa9adf0..9f48cda 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestCfArm.kt
@@ -16,11 +16,10 @@
 
 package com.android.server.wm.flicker.quickswitch
 
-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.Rect
-import com.android.server.wm.traces.common.service.PlatformConsts
+import android.tools.common.NavBar
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -32,13 +31,11 @@
 class QuickSwitchBetweenTwoAppsForwardTestCfArm(flicker: FlickerTest) :
     QuickSwitchBetweenTwoAppsForwardTest(flicker) {
     companion object {
-        private var startDisplayBounds = Rect.EMPTY
-
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL)
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
index b40ecac..b0d4e27 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
@@ -17,10 +17,10 @@
 package com.android.server.wm.flicker.quickswitch
 
 import android.platform.test.annotations.FlakyTest
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
 import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
 import org.junit.Assume
 import org.junit.Before
 import org.junit.FixMethodOrder
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 c03cd29..63299cb 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
@@ -18,17 +18,18 @@
 
 import android.platform.test.annotations.FlakyTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.common.datatypes.Rect
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.isShellTransitionsEnabled
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
-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
 import org.junit.Ignore
@@ -283,9 +284,9 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL),
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL),
                 // TODO: Test with 90 rotation
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt
index 8b21603..af671df 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTestCfArm.kt
@@ -16,10 +16,11 @@
 
 package com.android.server.wm.flicker.quickswitch
 
-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 android.tools.common.NavBar
+import android.tools.common.Rotation
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -35,9 +36,9 @@
         @JvmStatic
         fun getParams(): Collection<FlickerTest> {
             return FlickerTestFactory.nonRotationTests(
-                supportedNavigationModes = listOf(PlatformConsts.NavBar.MODE_GESTURAL),
+                supportedNavigationModes = listOf(NavBar.MODE_GESTURAL),
                 // TODO: Test with 90 rotation
-                supportedRotations = listOf(PlatformConsts.Rotation.ROTATION_0)
+                supportedRotations = listOf(Rotation.ROTATION_0)
             )
         }
     }
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 e7e39c6..4a4180b 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
@@ -18,13 +18,13 @@
 
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import 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.SimpleAppHelper
-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
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTestCfArm.kt
index 6420f79..0e6b20f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTestCfArm.kt
@@ -16,9 +16,9 @@
 
 package com.android.server.wm.flicker.rotation
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
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 74ecdde..3c0bbd6 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
@@ -17,12 +17,12 @@
 package com.android.server.wm.flicker.rotation
 
 import android.platform.test.annotations.Presubmit
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.apphelpers.StandardAppHelper
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
 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.helpers.StandardAppHelper
 import com.android.server.wm.flicker.helpers.setRotation
-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 1a69344..17b3b2b 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
@@ -18,16 +18,16 @@
 
 import android.platform.test.annotations.IwTest
 import android.platform.test.annotations.Presubmit
+import android.tools.common.ScenarioBuilder
+import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerBuilder
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import android.view.WindowManager
 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.ScenarioBuilder
 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.component.matchers.ComponentNameMatcher
 import org.junit.FixMethodOrder
 import org.junit.Ignore
 import org.junit.Test
@@ -108,8 +108,10 @@
     fun appWindowFullScreen() {
         flicker.assertWm {
             this.invoke("isFullScreen") {
-                val appWindow = it.windowState(testApp.`package`)
-                val flags = appWindow.windowState?.attributes?.flags ?: 0
+                val appWindow =
+                    it.windowState(testApp.`package`)
+                        ?: error("App window for package ${testApp.`package`} not found")
+                val flags = appWindow.windowState.attributes.flags
                 appWindow
                     .check { "isFullScreen" }
                     .that(flags.and(WindowManager.LayoutParams.FLAG_FULLSCREEN))
@@ -124,8 +126,10 @@
     fun appWindowSeamlessRotation() {
         flicker.assertWm {
             this.invoke("isRotationSeamless") {
-                val appWindow = it.windowState(testApp.`package`)
-                val rotationAnimation = appWindow.windowState?.attributes?.rotationAnimation ?: 0
+                val appWindow =
+                    it.windowState(testApp.`package`)
+                        ?: error("App window for package ${testApp.`package`} not found")
+                val rotationAnimation = appWindow.windowState.attributes.rotationAnimation
                 appWindow
                     .check { "isRotationSeamless" }
                     .that(
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTestCfArm.kt
index 0ebbf4e..b236d87 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTestCfArm.kt
@@ -16,9 +16,9 @@
 
 package com.android.server.wm.flicker.rotation
 
-import com.android.server.wm.flicker.FlickerTest
-import com.android.server.wm.flicker.FlickerTestFactory
-import com.android.server.wm.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.device.flicker.legacy.FlickerTest
+import android.tools.device.flicker.legacy.FlickerTestFactory
 import com.android.server.wm.flicker.testapp.ActivityOptions
 import org.junit.FixMethodOrder
 import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/test-apps/flickerapp/Android.bp b/tests/FlickerTests/test-apps/flickerapp/Android.bp
index 9b1262d..75e35ee 100644
--- a/tests/FlickerTests/test-apps/flickerapp/Android.bp
+++ b/tests/FlickerTests/test-apps/flickerapp/Android.bp
@@ -41,6 +41,7 @@
         "kotlin-stdlib",
         "kotlinx-coroutines-android",
         "wm-flicker-common-app-helpers",
+        "wm-flicker-common-assertions",
         "wm-flicker-window-extensions",
     ],
 }
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
index c7e5a5e..e59071b 100644
--- a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -29,6 +29,7 @@
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.Debug.MemoryInfo;
+import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.test.InstrumentationTestCase;
@@ -40,6 +41,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * This test is intended to measure the amount of memory applications use when
@@ -313,17 +315,19 @@
 
         public void run() {
             try {
-                String mimeType = mLaunchIntent.getType();
-                if (mimeType == null && mLaunchIntent.getData() != null
+                AtomicReference<String> mimeType = new AtomicReference<>(mLaunchIntent.getType());
+                if (mimeType.get() == null && mLaunchIntent.getData() != null
                         && "content".equals(mLaunchIntent.getData().getScheme())) {
-                    mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
-                            UserHandle.USER_CURRENT);
+                    mAm.getMimeTypeFilterAsync(mLaunchIntent.getData(), UserHandle.USER_CURRENT,
+                            new RemoteCallback(result -> {
+                                mimeType.set(result.getPairValue());
+                            }));
                 }
 
                 mAtm.startActivityAndWait(null,
                         getInstrumentation().getContext().getBasePackageName(),
                         getInstrumentation().getContext().getAttributionTag(), mLaunchIntent,
-                        mimeType, null, null, 0, mLaunchIntent.getFlags(), null, null,
+                        mimeType.get(), null, null, 0, mLaunchIntent.getFlags(), null, null,
                         UserHandle.USER_CURRENT_OR_SELF);
             } catch (RemoteException e) {
                 Log.w(TAG, "Error launching app", e);
diff --git a/tests/MidiTests/Android.bp b/tests/MidiTests/Android.bp
new file mode 100644
index 0000000..254770d
--- /dev/null
+++ b/tests/MidiTests/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 {
+    name: "MidiTests",
+    srcs: ["**/*.java"],
+    static_libs: [
+        "androidx.test.rules",
+        "mockito-target-inline-minus-junit4",
+        "platform-test-annotations",
+        "services.midi",
+        "truth-prebuilt",
+    ],
+    jni_libs: ["libdexmakerjvmtiagent"],
+    certificate: "platform",
+    platform_apis: true,
+    test_suites: ["device-tests"],
+}
diff --git a/tests/MidiTests/AndroidManifest.xml b/tests/MidiTests/AndroidManifest.xml
new file mode 100644
index 0000000..0ee1b449
--- /dev/null
+++ b/tests/MidiTests/AndroidManifest.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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.server.midi" >
+
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.MANAGE_USERS" />
+
+    <application android:debuggable="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+                     android:targetPackage="com.android.server.midi"
+                     android:label="MidiTests"/>
+</manifest>
diff --git a/tests/MidiTests/AndroidTest.xml b/tests/MidiTests/AndroidTest.xml
new file mode 100644
index 0000000..9320f0a
--- /dev/null
+++ b/tests/MidiTests/AndroidTest.xml
@@ -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.
+-->
+<configuration description="Runs sample instrumentation test.">
+    <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="MidiTests.apk"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
+    <option name="test-suite-tag" value="apct"/>
+    <option name="test-tag" value="MidiTests"/>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+        <option name="package" value="com.android.server.midi"/>
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner"/>
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
diff --git a/tests/MidiTests/OWNERS b/tests/MidiTests/OWNERS
new file mode 100644
index 0000000..af273a6
--- /dev/null
+++ b/tests/MidiTests/OWNERS
@@ -0,0 +1 @@
+include /services/midi/OWNERS
diff --git a/tests/MidiTests/TEST_MAPPING b/tests/MidiTests/TEST_MAPPING
new file mode 100644
index 0000000..60416a8
--- /dev/null
+++ b/tests/MidiTests/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "MidiTests"
+    }
+  ]
+}
diff --git a/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java b/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java
new file mode 100644
index 0000000..1659cc0
--- /dev/null
+++ b/tests/MidiTests/src/com/android/server/midi/MidiEventMultiSchedulerTest.java
@@ -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.server.midi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.midi.MidiEventMultiScheduler;
+import com.android.internal.midi.MidiEventScheduler;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+/**
+ * Unit tests for com.android.internal.midi.MidiEventMultiScheduler.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MidiEventMultiSchedulerTest {
+    private byte[] generateRandomByteStream(Random rnd, int size) {
+        byte[] output = new byte[size];
+        rnd.nextBytes(output);
+        return output;
+    }
+
+    private void compareByteArrays(byte[] expectedArray, byte[] outputArray) {
+        assertEquals(expectedArray.length, outputArray.length);
+        for (int i = 0; i < outputArray.length; i++) {
+            assertEquals(expectedArray[i], outputArray[i]);
+        }
+    }
+
+    private long timeFromNow(long milliseconds) {
+        return System.nanoTime() + 1000000L * milliseconds;
+    }
+
+    @Test
+    public void testMultiScheduler() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+            assertEquals(3, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+            MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+            MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0, (byte) 0xf7},
+                    0, 2, timeFromNow(100)));
+            scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1, (byte) 0xf2},
+                    0, 2, timeFromNow(200)));
+            scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf3, (byte) 0xf4},
+                    0, 2, timeFromNow(300)));
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf5, (byte) 0xf6},
+                    0, 2, timeFromNow(400)));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNotNull(scheduler0.getNextEvent(System.nanoTime()));
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNull(scheduler0.getNextEvent(System.nanoTime()));
+            assertNotNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNull(scheduler0.getNextEvent(System.nanoTime()));
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNotNull(scheduler2.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNotNull(scheduler0.getNextEvent(System.nanoTime()));
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testSchedulerLargeData() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+            assertEquals(1, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+
+            Random rnd = new Random(42);
+
+            final int arraySize = 1000;
+            byte[] expectedArray = generateRandomByteStream(rnd, arraySize);
+
+            scheduler0.add(scheduler0.createScheduledEvent(expectedArray, 0, arraySize,
+                    timeFromNow(100)));
+            assertTrue(multiScheduler.waitNextEvent());
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            compareByteArrays(expectedArray, event.data);
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testSchedulerClose() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+            assertEquals(1, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+            scheduler0.close();
+            // After all schedulers are closed, waitNextEvent() should return false.
+            assertFalse(multiScheduler.waitNextEvent());
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testSchedulerMultiClose() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+            assertEquals(3, multiScheduler.getNumEventSchedulers());
+            multiScheduler.close();
+            // After all schedulers are closed, waitNextEvent() should return false.
+            assertFalse(multiScheduler.waitNextEvent());
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testSchedulerNoPreemptiveClose() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+            assertEquals(3, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+            MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+            MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+            scheduler0.close();
+            scheduler1.close();
+            scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf5, (byte) 0xf6},
+                    0, 2, timeFromNow(100)));
+            assertTrue(multiScheduler.waitNextEvent());
+            scheduler2.close();
+            // After all schedulers are closed, waitNextEvent() should return false.
+            assertFalse(multiScheduler.waitNextEvent());
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testSchedulerSpamEvents() {
+        MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+        assertEquals(1, multiScheduler.getNumEventSchedulers());
+        MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+        // Create a msg with size 1
+        byte[] msg = new byte[1];
+        for (int i = 0; i < 1000; i++) {
+            msg[0] = (byte) i;
+            scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals(msg[0], event.data[0]);
+        }
+        assertNull(scheduler0.getNextEvent(System.nanoTime()));
+    }
+
+    @Test
+    public void testSchedulerSpamEventsPullLater() {
+        MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+        assertEquals(1, multiScheduler.getNumEventSchedulers());
+        MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+        // Create a msg with size 1
+        byte[] msg = new byte[1];
+        for (int i = 0; i < 1000; i++) {
+            msg[0] = (byte) i;
+            scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+        }
+
+        for (int i = 0; i < 1000; i++) {
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) i, event.data[0]);
+        }
+        assertNull(scheduler0.getNextEvent(System.nanoTime()));
+    }
+
+    @Test
+    public void testSchedulerSpamEventsCallbackLater() {
+        MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(1);
+        assertEquals(1, multiScheduler.getNumEventSchedulers());
+        MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+        // Create a msg with size 1
+        byte[] msg = new byte[1];
+        for (int i = 0; i < 1000; i++) {
+            msg[0] = (byte) i;
+            scheduler0.add(scheduler0.createScheduledEvent(msg, 0, 1, timeFromNow(0)));
+        }
+
+        for (int i = 0; i < 1000; i++) {
+            try {
+                assertTrue(multiScheduler.waitNextEvent());
+            } catch (InterruptedException ex) {
+            }
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) i, event.data[0]);
+        }
+        assertNull(scheduler0.getNextEvent(System.nanoTime()));
+    }
+
+    @Test
+    public void testMultiSchedulerOutOfOrder() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+            assertEquals(3, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+            MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+            MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf3},
+                    0, 1,
+                    timeFromNow(400)));
+            scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf2},
+                    0, 1,
+                    timeFromNow(300)));
+            scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1},
+                    0, 1,
+                    timeFromNow(200)));
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0},
+                    0, 1,
+                    timeFromNow(100)));
+
+            assertTrue(multiScheduler.waitNextEvent());
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf0, event.data[0]);
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNull(scheduler0.getNextEvent(System.nanoTime()));
+            event = (MidiEventScheduler.MidiEvent) scheduler1.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf1, event.data[0]);
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            assertNull(scheduler0.getNextEvent(System.nanoTime()));
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            event = (MidiEventScheduler.MidiEvent) scheduler2.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf2, event.data[0]);
+            assertTrue(multiScheduler.waitNextEvent());
+            event = (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf3, event.data[0]);
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+        } catch (InterruptedException ex) {
+
+        }
+    }
+
+    @Test
+    public void testMultiSchedulerOutOfOrderNegativeTime() {
+        try {
+            MidiEventMultiScheduler multiScheduler = new MidiEventMultiScheduler(3);
+            assertEquals(3, multiScheduler.getNumEventSchedulers());
+            MidiEventScheduler scheduler0 = multiScheduler.getEventScheduler(0);
+            MidiEventScheduler scheduler1 = multiScheduler.getEventScheduler(1);
+            MidiEventScheduler scheduler2 = multiScheduler.getEventScheduler(2);
+
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf3},
+                    0, 1,
+                    timeFromNow(-100)));
+            scheduler2.add(scheduler2.createScheduledEvent(new byte[]{(byte) 0xf2},
+                    0, 1,
+                    timeFromNow(-200)));
+            scheduler1.add(scheduler1.createScheduledEvent(new byte[]{(byte) 0xf1},
+                    0, 1,
+                    timeFromNow(-300)));
+            scheduler0.add(scheduler0.createScheduledEvent(new byte[]{(byte) 0xf0},
+                    0, 1,
+                    timeFromNow(-400)));
+
+            assertTrue(multiScheduler.waitNextEvent());
+            MidiEventScheduler.MidiEvent event =
+                    (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf0, event.data[0]);
+            assertTrue(multiScheduler.waitNextEvent());
+            event = (MidiEventScheduler.MidiEvent) scheduler1.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf1, event.data[0]);
+            assertTrue(multiScheduler.waitNextEvent());
+            event = (MidiEventScheduler.MidiEvent) scheduler2.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf2, event.data[0]);
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertTrue(multiScheduler.waitNextEvent());
+            event = (MidiEventScheduler.MidiEvent) scheduler0.getNextEvent(System.nanoTime());
+            assertNotNull(event);
+            assertEquals(1, event.count);
+            assertEquals((byte) 0xf3, event.data[0]);
+            assertNull(scheduler1.getNextEvent(System.nanoTime()));
+            assertNull(scheduler2.getNextEvent(System.nanoTime()));
+        } catch (InterruptedException ex) {
+
+        }
+    }
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferPresentationTests.kt
index 7a8d949..97398dc 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
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
 import junit.framework.Assert.assertEquals
 import junit.framework.Assert.assertTrue
 import org.junit.Test
@@ -170,4 +170,4 @@
             assertTrue(failures)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
index da53387..0cc18d6 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/BufferRejectionTests.kt
@@ -16,10 +16,11 @@
 package com.android.test
 
 import android.graphics.Point
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
 import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode
 import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
 import junit.framework.Assert.assertEquals
+import org.junit.Assert
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
@@ -45,8 +46,9 @@
             activity.mSurfaceProxy.waitUntilBufferDisplayed(3, 500 /* ms */)
         }
         // Verify we reject buffers since scaling mode == NATIVE_WINDOW_SCALING_MODE_FREEZE
-        LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
-
+        Assert.assertThrows(AssertionError::class.java) {
+            LayersTraceSubject(trace).layer("SurfaceView", 2)
+        }
         // Verify the next buffer is submitted with the correct size
         LayersTraceSubject(trace).layer("SurfaceView", 3).also {
             it.hasBufferSize(defaultBufferSize)
@@ -82,7 +84,9 @@
 
         // verify buffer size is reset to default buffer size
         LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
-        LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+        Assert.assertThrows(AssertionError::class.java) {
+            LayersTraceSubject(trace).layer("SurfaceView", 2)
+        }
         LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(bufferSize)
     }
 
@@ -110,7 +114,9 @@
 
         // verify buffer size is reset to default buffer size
         LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
-        LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+        Assert.assertThrows(AssertionError::class.java) {
+            LayersTraceSubject(trace).layer("SurfaceView", 2)
+        }
         LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(rotatedBufferSize)
         LayersTraceSubject(trace).layer("SurfaceView", 3)
                 .hasBufferOrientation(Transform.ROT_90.value)
@@ -144,10 +150,11 @@
         for (count in 0 until 5) {
             LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 1L)
                     .hasBufferSize(defaultBufferSize)
-            LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 2L)
-                    .doesNotExist()
+            Assert.assertThrows(AssertionError::class.java) {
+                LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 2L)
+            }
             LayersTraceSubject(trace).layer("SurfaceView", (count * 3) + 3L)
                     .hasBufferSize(bufferSize)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
index 2d6c664..6f4d11c 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/GeometryTests.kt
@@ -19,11 +19,12 @@
 import android.graphics.Point
 import android.graphics.Rect
 import android.os.SystemClock
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
 import com.android.test.SurfaceViewBufferTestBase.Companion.ScalingMode
 import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
 import junit.framework.Assert.assertEquals
 import junit.framework.Assert.assertTrue
+import org.junit.Assert
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
@@ -103,7 +104,9 @@
 
         // verify buffer size is reset to default buffer size
         LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
-        LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+        Assert.assertThrows(AssertionError::class.java) {
+            LayersTraceSubject(trace).layer("SurfaceView", 2)
+        }
         LayersTraceSubject(trace).layer("SurfaceView", 3).hasBufferSize(bufferSize)
     }
 
@@ -221,4 +224,4 @@
             it.hasBufferSize(defaultBufferSize)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
index cf4186d..e722ba5 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/InverseDisplayTransformTests.kt
@@ -16,9 +16,10 @@
 package com.android.test
 
 import android.graphics.Point
-import com.android.server.wm.flicker.traces.layers.LayersTraceSubject
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
 import com.android.test.SurfaceViewBufferTestBase.Companion.Transform
 import junit.framework.Assert.assertEquals
+import org.junit.Assert
 import org.junit.Assume.assumeFalse
 import org.junit.Before
 import org.junit.Test
@@ -70,7 +71,9 @@
 
         // verify buffer size is reset to default buffer size
         LayersTraceSubject(trace).layer("SurfaceView", 1).hasBufferSize(defaultBufferSize)
-        LayersTraceSubject(trace).layer("SurfaceView", 2).doesNotExist()
+        Assert.assertThrows(AssertionError::class.java) {
+            LayersTraceSubject(trace).layer("SurfaceView", 2)
+        }
         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 61d4095..be3ed71 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
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
 import junit.framework.Assert.assertEquals
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -87,4 +87,4 @@
             checkPixels(svBounds, Color.BLUE)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
index 6383da5..cf4cb8c 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceTracingTestBase.kt
@@ -21,9 +21,11 @@
 import android.graphics.Rect
 import android.util.Log
 import androidx.test.ext.junit.rules.ActivityScenarioRule
-import com.android.server.wm.flicker.monitor.LayersTraceMonitor
-import com.android.server.wm.flicker.monitor.withSFTracing
-import com.android.server.wm.traces.common.layers.LayersTrace
+import android.tools.common.flicker.subject.layers.LayerSubject
+import android.tools.common.traces.surfaceflinger.LayersTrace
+import android.tools.device.traces.io.ResultWriter
+import android.tools.device.traces.monitors.surfaceflinger.LayersTraceMonitor
+import android.tools.device.traces.monitors.withSFTracing
 import junit.framework.Assert
 import org.junit.After
 import org.junit.Before
@@ -52,8 +54,7 @@
     }
 
     fun withTrace(predicate: (it: MainActivity) -> Unit): LayersTrace {
-        return withSFTracing(TRACE_FLAGS,
-                outputDir = instrumentation.targetContext.dataDir.toPath()) {
+        return withSFTracing(TRACE_FLAGS) {
             scenarioRule.getScenario().onActivity {
                 predicate(it)
             }
@@ -61,8 +62,7 @@
     }
 
     fun withTrace(predicate: () -> Unit): LayersTrace {
-        return withSFTracing(TRACE_FLAGS,
-                outputDir = instrumentation.targetContext.dataDir.toPath()) {
+        return withSFTracing(TRACE_FLAGS) {
                 predicate()
         }
     }
@@ -84,8 +84,7 @@
     }
 
     private fun stopLayerTrace() {
-        val tmpDir = instrumentation.targetContext.dataDir.toPath()
-        LayersTraceMonitor(tmpDir).stop()
+        LayersTraceMonitor().stop(ResultWriter())
     }
 
     fun checkPixels(bounds: Rect, @ColorInt color: Int) {
@@ -117,4 +116,4 @@
         private const val TRACE_FLAGS =
                 (1 shl 0) or (1 shl 5) or (1 shl 6) // TRACE_CRITICAL | TRACE_BUFFERS | TRACE_SYNC
     }
-}
\ No newline at end of file
+}
diff --git a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
index 093c312..bba9678 100644
--- a/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
+++ b/tests/SurfaceViewBufferTests/src/com/android/test/SurfaceViewBufferTestBase.kt
@@ -18,6 +18,8 @@
 import android.app.Instrumentation
 import android.graphics.Point
 import android.provider.Settings
+import android.tools.common.datatypes.Size
+import android.tools.common.flicker.subject.layers.LayerSubject
 import androidx.test.InstrumentationRegistry
 import org.junit.After
 import org.junit.Before
@@ -69,6 +71,10 @@
         const val R8G8B8A8_UNORM = 1
         val defaultBufferSize = Point(640, 480)
 
+        fun LayerSubject.hasBufferSize(point: Point) = hasBufferSize(Size.from(point.x, point.y))
+
+        fun LayerSubject.hasLayerSize(point: Point) = hasLayerSize(Size.from(point.x, point.y))
+
         // system/window.h definitions
         enum class ScalingMode() {
             FREEZE, // = 0
@@ -94,4 +100,4 @@
             INVERSE_DISPLAY(0x08)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
index 722e671..6f4f7b1 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/ResizeTasksSyncTest.kt
@@ -16,14 +16,15 @@
 package com.android.test.taskembed
 
 import android.app.Instrumentation
-import android.graphics.Point
 import android.graphics.Rect
 import androidx.test.ext.junit.rules.ActivityScenarioRule
 import androidx.test.platform.app.InstrumentationRegistry
 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
+import android.tools.common.datatypes.Size
+import android.tools.common.flicker.subject.layers.LayersTraceSubject
+import android.tools.device.traces.io.ResultWriter
+import android.tools.device.traces.monitors.surfaceflinger.LayersTraceMonitor
+import android.tools.device.traces.monitors.withSFTracing
 import org.junit.After
 import org.junit.Before
 import org.junit.FixMethodOrder
@@ -46,8 +47,10 @@
 
     @Before
     fun setup() {
-        val tmpDir = instrumentation.targetContext.dataDir.toPath()
-        LayersTraceMonitor(tmpDir).stop()
+        val monitor = LayersTraceMonitor()
+        if (monitor.isEnabled) {
+            monitor.stop(ResultWriter())
+        }
         val firstTaskBounds = Rect(0, 0, 1080, 1000)
         val secondTaskBounds = Rect(0, 1000, 1080, 2000)
 
@@ -68,8 +71,7 @@
         val firstBounds = Rect(0, 0, 1080, 800)
         val secondBounds = Rect(0, 1000, 1080, 1800)
 
-        val trace = withSFTracing(TRACE_FLAGS,
-                outputDir = instrumentation.targetContext.dataDir.toPath()) {
+        val trace = withSFTracing(TRACE_FLAGS) {
             lateinit var resizeReadyLatch: CountDownLatch
             scenarioRule.getScenario().onActivity {
                 resizeReadyLatch = it.resizeTaskView(firstBounds, secondBounds)
@@ -91,13 +93,13 @@
 
         // verify buffer size should be changed to expected values.
         LayersTraceSubject(trace).layer(FIRST_ACTIVITY, frame.toLong()).also {
-            val firstTaskSize = Point(firstBounds.width(), firstBounds.height())
+            val firstTaskSize = Size.from(firstBounds.width(), firstBounds.height())
             it.hasLayerSize(firstTaskSize)
             it.hasBufferSize(firstTaskSize)
         }
 
         LayersTraceSubject(trace).layer(SECOND_ACTIVITY, frame.toLong()).also {
-            val secondTaskSize = Point(secondBounds.width(), secondBounds.height())
+            val secondTaskSize = Size.from(secondBounds.width(), secondBounds.height())
             it.hasLayerSize(secondTaskSize)
             it.hasBufferSize(secondTaskSize)
         }
@@ -108,4 +110,4 @@
         private const val FIRST_ACTIVITY = "Activity1"
         private const val SECOND_ACTIVITY = "Activity2"
     }
-}
\ No newline at end of file
+}
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java b/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.java
new file mode 100644
index 0000000..ad701e5
--- /dev/null
+++ b/tests/UsbTests/src/com/android/server/usb/UsbMidiPacketConverterTest.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.server.usb;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Unit tests for com.android.server.usb.UsbMidiPacketConverter.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class UsbMidiPacketConverterTest {
+    private byte[] generateRandomByteStream(Random rnd, int size) {
+        byte[] output = new byte[size];
+        rnd.nextBytes(output);
+        return output;
+    }
+
+    private void compareByteArrays(byte[] expectedArray, byte[] outputArray) {
+        assertEquals(expectedArray.length, outputArray.length);
+        for (int i = 0; i < outputArray.length; i++) {
+            assertEquals(expectedArray[i], outputArray[i]);
+        }
+    }
+
+    @Test
+    public void testDecoderSinglePacket() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createDecoders(2);
+        byte[] input = new byte[] {0x19 /* Cable 1 Note-On */, (byte) 0x91, 0x33, 0x66};
+        byte[] expectedOutputCable0 = new byte[] {};
+        byte[] expectedOutputCable1 = new byte[] {(byte) 0x91, 0x33, 0x66};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+        compareByteArrays(expectedOutputCable1, actualOutputCable1);
+    }
+
+    @Test
+    public void testDecoderMultiplePackets() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createDecoders(4);
+        byte[] input = new byte[] {
+                0x1B /* Cable 1 Control Change */, (byte) 0xB4, 0x55, 0x6E,
+                0x35 /* Cable 3 Single byte SysEx */, (byte) 0xF8, 0x00, 0x00,
+                0x02 /* Cable 0 Two byte System Common */, (byte) 0xF3, 0x12, 0x00};
+        byte[] expectedOutputCable0 = new byte[] {(byte) 0xF3, 0x12};
+        byte[] expectedOutputCable1 = new byte[] {(byte) 0xB4, 0x55, 0x6E};
+        byte[] expectedOutputCable2 = new byte[] {};
+        byte[] expectedOutputCable3 = new byte[] {(byte) 0xF8};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+        byte[] actualOutputCable2 = usbMidiPacketConverter.pullDecodedMidiPackets(2);
+        byte[] actualOutputCable3 = usbMidiPacketConverter.pullDecodedMidiPackets(3);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+        compareByteArrays(expectedOutputCable1, actualOutputCable1);
+        compareByteArrays(expectedOutputCable2, actualOutputCable2);
+        compareByteArrays(expectedOutputCable3, actualOutputCable3);
+    }
+
+    @Test
+    public void testDecoderSysExEndFirstByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createDecoders(2);
+        byte[] input = new byte[] {
+                0x14 /* Cable 1 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x15 /* Cable 1 Single byte SysEx End */, (byte) 0xF7, 0x00, 0x00};
+        byte[] expectedOutputCable0 = new byte[] {};
+        byte[] expectedOutputCable1 = new byte[] {
+                (byte) 0xF0, 0x00, 0x01,
+                (byte) 0xF7};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        byte[] actualOutputCable1 = usbMidiPacketConverter.pullDecodedMidiPackets(1);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+        compareByteArrays(expectedOutputCable1, actualOutputCable1);
+    }
+
+    @Test
+    public void testDecoderSysExEndSecondByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createDecoders(1);
+        byte[] input = new byte[] {
+                0x04 /* Cable 0 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x06 /* Cable 0 Two byte SysEx End */, 0x02, (byte) 0xF7, 0x00};
+        byte[] expectedOutputCable0 = new byte[] {
+                (byte) 0xF0, 0x00, 0x01,
+                0x02, (byte) 0xF7};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+    }
+
+    @Test
+    public void testDecoderSysExEndThirdByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        byte[] input = new byte[] {
+                0x04 /* Cable 0 SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x07 /* Cable 0 Three byte SysEx End */, 0x02, 0x03, (byte) 0xF7};
+        usbMidiPacketConverter.createDecoders(1);
+        byte[] expectedOutputCable0 = new byte[] {
+                (byte) 0xF0, 0x00, 0x01,
+                0x02, 0x03, (byte) 0xF7};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+    }
+
+    @Test
+    public void testDecoderSysExStartEnd() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        byte[] input = new byte[] {
+                0x06 /* Cable 0 Two byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+        usbMidiPacketConverter.createDecoders(1);
+        byte[] expectedOutputCable0 = new byte[] {
+                (byte) 0xF0, (byte) 0xF7};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+    }
+
+    @Test
+    public void testDecoderSysExStartByteEnd() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        byte[] input = new byte[] {
+                0x07 /* Cable 0 Three byte SysEx End */, (byte) 0xF0, 0x44, (byte) 0xF7};
+        usbMidiPacketConverter.createDecoders(1);
+        byte[] expectedOutputCable0 = new byte[] {
+                (byte) 0xF0, 0x44, (byte) 0xF7};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+    }
+
+    @Test
+    public void testDecoderDefaultToFirstCable() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        byte[] input = new byte[] {0x49 /* Cable 4 Note-On */, (byte) 0x91, 0x22, 0x33};
+        usbMidiPacketConverter.createDecoders(1);
+        byte[] expectedOutputCable0 = new byte[] {
+                (byte) 0x91, 0x22, 0x33};
+        usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+        byte[] actualOutputCable0 = usbMidiPacketConverter.pullDecodedMidiPackets(0);
+        compareByteArrays(expectedOutputCable0, actualOutputCable0);
+    }
+
+    @Test
+    public void testDecoderLargePacketDoesNotCrash() {
+        for (long seed = 1001; seed < 5000; seed += 777) {
+            UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+            usbMidiPacketConverter.createDecoders(3);
+            Random rnd = new Random(seed);
+            byte[] input = generateRandomByteStream(rnd, 1003 /* arbitrary large size */);
+            usbMidiPacketConverter.decodeMidiPackets(input, input.length);
+            usbMidiPacketConverter.pullDecodedMidiPackets(0);
+            usbMidiPacketConverter.pullDecodedMidiPackets(1);
+            usbMidiPacketConverter.pullDecodedMidiPackets(2);
+        }
+    }
+
+    @Test
+    public void testEncoderBasic() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {(byte) 0x91 /* Note-On */, 0x33, 0x66};
+        byte[] expectedOutput = new byte[] {
+                0x09 /* Cable 0 Note-On */, (byte) 0x91, 0x33, 0x66};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderMultiplePackets() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(3);
+        byte[] inputCable2 = new byte[] {
+                (byte) 0xB4 /* Control Change */, 0x55, 0x6E};
+        byte[] inputCable1 = new byte[] {
+                (byte) 0xF8 /* Timing Clock (Single Byte) */,
+                (byte) 0xF3 /* Song Select (Two Bytes) */, 0x12};
+        byte[] expectedOutput = new byte[] {
+            0x2B /* Cable 2 Control Change */, (byte) 0xB4, 0x55, 0x6E,
+            0x15 /* Cable 1 Timing Clock */, (byte) 0xF8, 0x00, 0x00,
+            0x12 /* Cable 1 Two Byte System Common */, (byte) 0xF3, 0x12, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(inputCable2, inputCable2.length, 2);
+        usbMidiPacketConverter.encodeMidiPackets(inputCable1, inputCable1.length, 1);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderWeavePackets() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(2);
+        byte[] inputCable1Msg1 = new byte[] {
+                (byte) 0x93 /* Note-On */, 0x23, 0x43};
+        byte[] inputCable0Msg = new byte[] {
+                (byte) 0xB4 /* Control Change */, 0x65, 0x26};
+        byte[] inputCable1Msg2 = new byte[] {
+                (byte) 0xA4 /* Poly-KeyPress */, 0x52, 0x76};
+        byte[] expectedOutput = new byte[] {
+                0x19 /* Cable 1 Note-On */, (byte) 0x93, 0x23, 0x43,
+                0x0B /* Cable 0 Control Change */, (byte) 0xB4, 0x65, 0x26,
+                0x1A /* Cable 1 Poly-KeyPress */, (byte) 0xA4, 0x52, 0x76};
+        usbMidiPacketConverter.encodeMidiPackets(inputCable1Msg1, inputCable1Msg1.length, 1);
+        usbMidiPacketConverter.encodeMidiPackets(inputCable0Msg, inputCable0Msg.length, 0);
+        usbMidiPacketConverter.encodeMidiPackets(inputCable1Msg2, inputCable1Msg2.length, 1);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderSysExEndFirstByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+                (byte) 0xF7 /* SysEx End */};
+        byte[] expectedOutput = new byte[] {
+                0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x05 /* Cable 0 One Byte SysEx End */, (byte) 0xF7, 0x00, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderSysExEndSecondByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+                0x02, (byte) 0xF7 /* SysEx End */};
+        byte[] expectedOutput = new byte[] {
+                0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x06 /* Cable 0 Two Byte SysEx End */, 0x02, (byte) 0xF7, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderSysExEndThirdByte() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, 0x00, 0x01,
+                0x02, 0x03, (byte) 0xF7 /* SysEx End */};
+        byte[] expectedOutput = new byte[] {
+                0x04 /* Cable 0 Three Byte SysEx Start */, (byte) 0xF0, 0x00, 0x01,
+                0x07 /* Cable 0 Three Byte SysEx End */, 0x02, 0x03, (byte) 0xF7};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderSysExStartEnd() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, (byte) 0xF7 /* SysEx End */};
+        byte[] expectedOutput = new byte[] {
+                0x06 /* Cable 0 Two Byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderSysExStartByteEnd() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, 0x44, (byte) 0xF7 /* SysEx End */};
+        byte[] expectedOutput = new byte[] {
+                0x07 /* Cable 0 Three Byte SysEx End */, (byte) 0xF0, 0x44, (byte) 0xF7};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderMultiplePulls() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(1);
+
+        byte[] input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, 0x44, 0x55,
+                0x66, 0x77}; // 0x66 and 0x77 will not be pulled the first time
+        byte[] expectedOutput = new byte[] {
+                0x04 /* SysEx Start */, (byte) 0xF0, 0x44, 0x55};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+
+        input = new byte[] {
+                0x11, // Combined with 0x66 and 0x77 above
+                0x22, (byte) 0xF7 /* SysEx End */};
+        expectedOutput = new byte[] {
+                0x04 /* Cable 0 SysEx Continue */, 0x66, 0x77, 0x11,
+                0x06 /* Cable 0 Two Byte SysEx End */, 0x22, (byte) 0xF7, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+
+        input = new byte[] {
+                (byte) 0xF0 /* SysEx Start */, (byte) 0xF7 /* SysEx End */};
+        expectedOutput = new byte[] {
+                0x06 /* Cable 0 Two Byte SysEx End */, (byte) 0xF0, (byte) 0xF7, 0x00};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 0);
+        output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderDefaultToFirstCable() {
+        UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+        usbMidiPacketConverter.createEncoders(2);
+        byte[] input = new byte[] {(byte) 0x91 /* Note-On */, 0x22, 0x33};
+        byte[] expectedOutput = new byte[] {
+                0x09 /* Cable 0 Note-On */, (byte) 0x91, 0x22, 0x33};
+        usbMidiPacketConverter.encodeMidiPackets(input, input.length, 4);
+        byte[] output = usbMidiPacketConverter.pullEncodedMidiPackets();
+        compareByteArrays(expectedOutput, output);
+    }
+
+    @Test
+    public void testEncoderLargePacketDoesNotCrash() {
+        for (long seed = 234; seed < 4000; seed += 666) {
+            Random rnd = new Random(seed);
+            UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+            usbMidiPacketConverter.createEncoders(4);
+            for (int cableNumber = 0; cableNumber < 4; cableNumber++) {
+                byte[] input = generateRandomByteStream(rnd, 1003 /* arbitrary large size */);
+                usbMidiPacketConverter.encodeMidiPackets(input, input.length, cableNumber);
+            }
+            usbMidiPacketConverter.pullEncodedMidiPackets();
+        }
+    }
+
+    @Test
+    public void testEncodeDecode() {
+        final int bufferSize = 30;
+        final int numCables = 16;
+        final int bytesToEncodePerEncoding = 10;
+        byte[][] rawMidi = new byte[numCables][bufferSize];
+        for (long seed = 45; seed < 3000; seed += 300) {
+            Random rnd = new Random(seed);
+            for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+                rawMidi[cableNumber] =  generateRandomByteStream(rnd, bufferSize);
+
+                // Change the last byte to SysEx End.
+                // This way the encoder is guaranteed to flush all packets.
+                rawMidi[cableNumber][bufferSize - 1] = (byte) 0xF7;
+            }
+            UsbMidiPacketConverter usbMidiPacketConverter = new UsbMidiPacketConverter();
+            usbMidiPacketConverter.createEncoders(numCables);
+            // Encode packets and interweave them
+            for (int startByte = 0; startByte < bufferSize;
+                    startByte += bytesToEncodePerEncoding) {
+                for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+                    byte[] bytesToEncode = Arrays.copyOfRange(rawMidi[cableNumber], startByte,
+                            startByte + bytesToEncodePerEncoding);
+                    usbMidiPacketConverter.encodeMidiPackets(bytesToEncode, bytesToEncode.length,
+                            cableNumber);
+                }
+            }
+            byte[] usbMidi = usbMidiPacketConverter.pullEncodedMidiPackets();
+
+            usbMidiPacketConverter.createDecoders(numCables);
+
+            // Now decode the MIDI packets to check if they are the same as the original
+            usbMidiPacketConverter.decodeMidiPackets(usbMidi, usbMidi.length);
+            for (int cableNumber = 0; cableNumber < numCables; cableNumber++) {
+                byte[] decodedRawMidi = usbMidiPacketConverter.pullDecodedMidiPackets(cableNumber);
+                compareByteArrays(rawMidi[cableNumber], decodedRawMidi);
+            }
+        }
+    }
+}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
similarity index 95%
rename from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
rename to wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
index 35d5c15..f9c4829 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.sharedconnectivity.app;
 
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable HotspotNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
similarity index 69%
rename from wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java
rename to wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
index af4fd4a..5cf19fb 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetwork.java
@@ -25,22 +25,22 @@
 import android.net.wifi.sharedconnectivity.service.SharedConnectivityService;
 import android.os.Parcel;
 import android.os.Parcelable;
-
+import android.util.ArraySet;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
 import java.util.Objects;
+import java.util.Set;
 
 /**
- * A data class representing an Instant Tether network.
+ * A data class representing a hotspot 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 {
+public final class HotspotNetwork implements Parcelable {
     /**
      * Remote device is connected to the internet via an unknown connection.
      */
@@ -71,34 +71,44 @@
             NETWORK_TYPE_WIFI,
             NETWORK_TYPE_ETHERNET
     })
-    public @interface NetworkType {}
+    public @interface NetworkType {
+    }
 
     private final long mDeviceId;
-    private final DeviceInfo mDeviceInfo;
-    @NetworkType private final int mNetworkType;
+    private final NetworkProviderInfo mNetworkProviderInfo;
+    @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;
+    @Nullable
+    private final String mHotspotSsid;
+    @Nullable
+    private final String mHotspotBssid;
+    @Nullable
+    @SecurityType
+    private final ArraySet<Integer> mHotspotSecurityTypes;
 
     /**
-     * Builder class for {@link TetherNetwork}.
+     * Builder class for {@link HotspotNetwork}.
      */
     public static final class Builder {
         private long mDeviceId = -1;
-        private DeviceInfo mDeviceInfo;
-        @NetworkType private int mNetworkType;
+        private NetworkProviderInfo mNetworkProviderInfo;
+        @NetworkType
+        private int mNetworkType;
         private String mNetworkName;
-        @Nullable private String mHotspotSsid;
-        @Nullable private String mHotspotBssid;
-        @Nullable @SecurityType private int[] mHotspotSecurityTypes;
-
-        public Builder() {}
+        @Nullable
+        private String mHotspotSsid;
+        @Nullable
+        private String mHotspotBssid;
+        @Nullable
+        @SecurityType
+        private final ArraySet<Integer> mHotspotSecurityTypes =
+                new ArraySet<>();
 
         /**
          * Set the remote device ID.
          *
-         * @param deviceId Locally unique ID for this Instant Tether network.
+         * @param deviceId Locally unique ID for this Hotspot network.
          * @return Returns the Builder object.
          */
         @NonNull
@@ -110,12 +120,12 @@
         /**
          * Sets information about the device providing connectivity.
          *
-         * @param deviceInfo The device information object.
+         * @param networkProviderInfo The device information object.
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setDeviceInfo(@NonNull DeviceInfo deviceInfo) {
-            mDeviceInfo = deviceInfo;
+        public Builder setNetworkProviderInfo(@NonNull NetworkProviderInfo networkProviderInfo) {
+            mNetworkProviderInfo = networkProviderInfo;
             return this;
         }
 
@@ -126,7 +136,7 @@
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setNetworkType(@NetworkType int networkType) {
+        public Builder setHostNetworkType(@NetworkType int networkType) {
             mNetworkType = networkType;
             return this;
         }
@@ -168,28 +178,27 @@
         }
 
         /**
-         * Sets the hotspot security types supported by the remote device, or null if hotspot is
-         * off.
+         * Adds a security type supported by the hotspot created by the remote device.
          *
-         * @param hotspotSecurityTypes The array of security types supported by the hotspot.
+         * @param hotspotSecurityType A security type supported by the hotspot.
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setHotspotSecurityTypes(@NonNull @SecurityType int[] hotspotSecurityTypes) {
-            mHotspotSecurityTypes = hotspotSecurityTypes;
+        public Builder addHotspotSecurityType(@SecurityType int hotspotSecurityType) {
+            mHotspotSecurityTypes.add(hotspotSecurityType);
             return this;
         }
 
         /**
-         * Builds the {@link TetherNetwork} object.
+         * Builds the {@link HotspotNetwork} object.
          *
-         * @return Returns the built {@link TetherNetwork} object.
+         * @return Returns the built {@link HotspotNetwork} object.
          */
         @NonNull
-        public TetherNetwork build() {
-            return new TetherNetwork(
+        public HotspotNetwork build() {
+            return new HotspotNetwork(
                     mDeviceId,
-                    mDeviceInfo,
+                    mNetworkProviderInfo,
                     mNetworkType,
                     mNetworkName,
                     mHotspotSsid,
@@ -211,30 +220,30 @@
         }
     }
 
-    private TetherNetwork(
+    private HotspotNetwork(
             long deviceId,
-            DeviceInfo deviceInfo,
+            NetworkProviderInfo networkProviderInfo,
             @NetworkType int networkType,
             @NonNull String networkName,
             @Nullable String hotspotSsid,
             @Nullable String hotspotBssid,
-            @Nullable @SecurityType int[] hotspotSecurityTypes) {
+            @Nullable @SecurityType ArraySet<Integer> hotspotSecurityTypes) {
         validate(deviceId,
                 networkType,
                 networkName);
         mDeviceId = deviceId;
-        mDeviceInfo = deviceInfo;
+        mNetworkProviderInfo = networkProviderInfo;
         mNetworkType = networkType;
         mNetworkName = networkName;
         mHotspotSsid = hotspotSsid;
         mHotspotBssid = hotspotBssid;
-        mHotspotSecurityTypes = hotspotSecurityTypes;
+        mHotspotSecurityTypes = new ArraySet<>(hotspotSecurityTypes);
     }
 
     /**
      * Gets the remote device ID.
      *
-     * @return Returns the locally unique ID for this Instant Tether network.
+     * @return Returns the locally unique ID for this Hotspot network.
      */
     public long getDeviceId() {
         return mDeviceId;
@@ -243,11 +252,11 @@
     /**
      * Gets information about the device providing connectivity.
      *
-     * @return Returns the information of the device providing the Instant Tether network.
+     * @return Returns the information of the device providing the Hotspot network.
      */
     @NonNull
-    public DeviceInfo getDeviceInfo() {
-        return mDeviceInfo;
+    public NetworkProviderInfo getNetworkProviderInfo() {
+        return mNetworkProviderInfo;
     }
 
     /**
@@ -256,7 +265,7 @@
      * @return Returns the network type as represented by IntDef {@link NetworkType}.
      */
     @NetworkType
-    public int getNetworkType() {
+    public int getHostNetworkType() {
         return mNetworkType;
     }
 
@@ -293,31 +302,31 @@
     /**
      * Gets the hotspot security types supported by the remote device.
      *
-     * @return Returns the array of security types supported by the hotspot.
+     * @return Returns a set of the security types supported by the hotspot.
      */
-    @Nullable
+    @NonNull
     @SecurityType
-    public int[] getHotspotSecurityTypes() {
+    public Set<Integer> getHotspotSecurityTypes() {
         return mHotspotSecurityTypes;
     }
 
     @Override
     public boolean equals(Object obj) {
-        if (!(obj instanceof TetherNetwork)) return false;
-        TetherNetwork other = (TetherNetwork) obj;
+        if (!(obj instanceof HotspotNetwork)) return false;
+        HotspotNetwork other = (HotspotNetwork) obj;
         return mDeviceId == other.getDeviceId()
-                && Objects.equals(mDeviceInfo, other.getDeviceInfo())
-                && mNetworkType == other.getNetworkType()
+                && Objects.equals(mNetworkProviderInfo, other.getNetworkProviderInfo())
+                && mNetworkType == other.getHostNetworkType()
                 && Objects.equals(mNetworkName, other.getNetworkName())
                 && Objects.equals(mHotspotSsid, other.getHotspotSsid())
                 && Objects.equals(mHotspotBssid, other.getHotspotBssid())
-                && Arrays.equals(mHotspotSecurityTypes, other.getHotspotSecurityTypes());
+                && Objects.equals(mHotspotSecurityTypes, other.getHotspotSecurityTypes());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mDeviceId, mDeviceInfo, mNetworkName, mHotspotSsid, mHotspotBssid,
-                Arrays.hashCode(mHotspotSecurityTypes));
+        return Objects.hash(mDeviceId, mNetworkProviderInfo, mNetworkName, mHotspotSsid,
+                mHotspotBssid, mHotspotSecurityTypes);
     }
 
     @Override
@@ -328,49 +337,49 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeLong(mDeviceId);
-        mDeviceInfo.writeToParcel(dest, flags);
+        mNetworkProviderInfo.writeToParcel(dest, flags);
         dest.writeInt(mNetworkType);
         dest.writeString(mNetworkName);
         dest.writeString(mHotspotSsid);
         dest.writeString(mHotspotBssid);
-        dest.writeIntArray(mHotspotSecurityTypes);
+        dest.writeArraySet(mHotspotSecurityTypes);
     }
 
     /**
-     * Creates a {@link TetherNetwork} object from a parcel.
+     * Creates a {@link HotspotNetwork} object from a parcel.
      *
      * @hide
      */
     @NonNull
-    public static TetherNetwork readFromParcel(@NonNull Parcel in) {
-        return new TetherNetwork(in.readLong(), DeviceInfo.readFromParcel(in),
+    public static HotspotNetwork readFromParcel(@NonNull Parcel in) {
+        return new HotspotNetwork(in.readLong(), NetworkProviderInfo.readFromParcel(in),
                 in.readInt(), in.readString(), in.readString(), in.readString(),
-                in.createIntArray());
+                (ArraySet<Integer>) in.readArraySet(null));
     }
 
     @NonNull
-    public static final Creator<TetherNetwork> CREATOR = new Creator<>() {
+    public static final Creator<HotspotNetwork> CREATOR = new Creator<>() {
         @Override
-        public TetherNetwork createFromParcel(Parcel in) {
+        public HotspotNetwork createFromParcel(Parcel in) {
             return readFromParcel(in);
         }
 
         @Override
-        public TetherNetwork[] newArray(int size) {
-            return new TetherNetwork[size];
+        public HotspotNetwork[] newArray(int size) {
+            return new HotspotNetwork[size];
         }
     };
 
     @Override
     public String toString() {
-        return new StringBuilder("TetherNetwork[")
+        return new StringBuilder("HotspotNetwork[")
                 .append("deviceId=").append(mDeviceId)
                 .append(", networkType=").append(mNetworkType)
-                .append(", deviceInfo=").append(mDeviceInfo.toString())
+                .append(", networkProviderInfo=").append(mNetworkProviderInfo.toString())
                 .append(", networkName=").append(mNetworkName)
                 .append(", hotspotSsid=").append(mHotspotSsid)
                 .append(", hotspotBssid=").append(mHotspotBssid)
-                .append(", hotspotSecurityTypes=").append(Arrays.toString(mHotspotSecurityTypes))
+                .append(", hotspotSecurityTypes=").append(mHotspotSecurityTypes.toString())
                 .append("]").toString();
     }
 }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
similarity index 93%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
index 35d5c15..d32d15e 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.sharedconnectivity.app;
 
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable HotspotNetworkConnectionStatus;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
similarity index 65%
rename from wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java
rename to wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
index 3cf44ed..7a50223 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatus.java
@@ -28,23 +28,23 @@
 import java.util.Objects;
 
 /**
- * The status of a connection to an instant tether network after the client called
- * {@link SharedConnectivityManager#connectTetherNetwork}.
+ * The status of a connection to a hotspot network after the client called
+ * {@link SharedConnectivityManager#connectHotspotNetwork}.
  *
  * @hide
  */
 @SystemApi
-public final class TetherNetworkConnectionStatus implements Parcelable {
+public final class HotspotNetworkConnectionStatus implements Parcelable {
 
     /**
      * Connection status is unknown.
      */
-    public static final int CONNECTION_STATUS_UNKNOWN  = 0;
+    public static final int CONNECTION_STATUS_UNKNOWN = 0;
 
     /**
      * The connection is being initiated.
      */
-    public static final int CONNECTION_STATUS_ENABLING_HOTSPOT  = 1;
+    public static final int CONNECTION_STATUS_ENABLING_HOTSPOT = 1;
 
     /**
      * Device providing the hotspot failed to initiate it.
@@ -102,22 +102,23 @@
             CONNECTION_STATUS_ENABLING_HOTSPOT_TIMEOUT,
             CONNECTION_STATUS_CONNECT_TO_HOTSPOT_FAILED,
     })
-    public @interface ConnectionStatus {}
+    public @interface ConnectionStatus {
+    }
 
-    @ConnectionStatus private final int mStatus;
-    private final TetherNetwork mTetherNetwork;
+    @ConnectionStatus
+    private final int mStatus;
+    private final HotspotNetwork mHotspotNetwork;
     private final Bundle mExtras;
 
     /**
-     * Builder class for {@link TetherNetworkConnectionStatus}.
+     * Builder class for {@link HotspotNetworkConnectionStatus}.
      */
     public static final class Builder {
-        @ConnectionStatus private int mStatus;
-        private TetherNetwork mTetherNetwork;
+        @ConnectionStatus
+        private int mStatus;
+        private HotspotNetwork mHotspotNetwork;
         private Bundle mExtras;
 
-        public Builder() {}
-
         /**
          * Sets the status of the connection
          *
@@ -130,13 +131,13 @@
         }
 
         /**
-         * Sets the {@link TetherNetwork} object of the connection.
+         * Sets the {@link HotspotNetwork} object of the connection.
          *
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setTetherNetwork(@NonNull TetherNetwork tetherNetwork) {
-            mTetherNetwork = tetherNetwork;
+        public Builder setHotspotNetwork(@NonNull HotspotNetwork hotspotNetwork) {
+            mHotspotNetwork = hotspotNetwork;
             return this;
         }
 
@@ -152,20 +153,21 @@
         }
 
         /**
-         * Builds the {@link TetherNetworkConnectionStatus} object.
+         * Builds the {@link HotspotNetworkConnectionStatus} object.
          *
-         * @return Returns the built {@link TetherNetworkConnectionStatus} object.
+         * @return Returns the built {@link HotspotNetworkConnectionStatus} object.
          */
         @NonNull
-        public TetherNetworkConnectionStatus build() {
-            return new TetherNetworkConnectionStatus(mStatus, mTetherNetwork, mExtras);
+        public HotspotNetworkConnectionStatus build() {
+            return new HotspotNetworkConnectionStatus(mStatus, mHotspotNetwork, mExtras);
         }
     }
 
-    private TetherNetworkConnectionStatus(@ConnectionStatus int status, TetherNetwork tetherNetwork,
+    private HotspotNetworkConnectionStatus(@ConnectionStatus int status,
+            HotspotNetwork hotspotNetwork,
             Bundle extras) {
         mStatus = status;
-        mTetherNetwork = tetherNetwork;
+        mHotspotNetwork = hotspotNetwork;
         mExtras = extras;
     }
 
@@ -180,13 +182,13 @@
     }
 
     /**
-     * Gets the {@link TetherNetwork} object of the connection.
+     * Gets the {@link HotspotNetwork} object of the connection.
      *
-     * @return Returns a TetherNetwork object.
+     * @return Returns a HotspotNetwork object.
      */
     @NonNull
-    public TetherNetwork getTetherNetwork() {
-        return mTetherNetwork;
+    public HotspotNetwork getHotspotNetwork() {
+        return mHotspotNetwork;
     }
 
     /**
@@ -201,15 +203,15 @@
 
     @Override
     public boolean equals(Object obj) {
-        if (!(obj instanceof TetherNetworkConnectionStatus)) return false;
-        TetherNetworkConnectionStatus other = (TetherNetworkConnectionStatus) obj;
+        if (!(obj instanceof HotspotNetworkConnectionStatus)) return false;
+        HotspotNetworkConnectionStatus other = (HotspotNetworkConnectionStatus) obj;
         return mStatus == other.getStatus()
-                && Objects.equals(mTetherNetwork, other.getTetherNetwork());
+                && Objects.equals(mHotspotNetwork, other.getHotspotNetwork());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mStatus, mTetherNetwork);
+        return Objects.hash(mStatus, mHotspotNetwork);
     }
 
     @Override
@@ -220,39 +222,39 @@
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mStatus);
-        mTetherNetwork.writeToParcel(dest, flags);
+        mHotspotNetwork.writeToParcel(dest, flags);
         dest.writeBundle(mExtras);
     }
 
     /**
-     * Creates a {@link TetherNetworkConnectionStatus} object from a parcel.
+     * Creates a {@link HotspotNetworkConnectionStatus} object from a parcel.
      *
      * @hide
      */
     @NonNull
-    public static TetherNetworkConnectionStatus readFromParcel(@NonNull Parcel in) {
-        return new TetherNetworkConnectionStatus(in.readInt(),
-                TetherNetwork.readFromParcel(in), in.readBundle());
+    public static HotspotNetworkConnectionStatus readFromParcel(@NonNull Parcel in) {
+        return new HotspotNetworkConnectionStatus(in.readInt(),
+                HotspotNetwork.readFromParcel(in), in.readBundle());
     }
 
     @NonNull
-    public static final Creator<TetherNetworkConnectionStatus> CREATOR = new Creator<>() {
+    public static final Creator<HotspotNetworkConnectionStatus> CREATOR = new Creator<>() {
         @Override
-        public TetherNetworkConnectionStatus createFromParcel(Parcel in) {
+        public HotspotNetworkConnectionStatus createFromParcel(Parcel in) {
             return readFromParcel(in);
         }
 
         @Override
-        public TetherNetworkConnectionStatus[] newArray(int size) {
-            return new TetherNetworkConnectionStatus[size];
+        public HotspotNetworkConnectionStatus[] newArray(int size) {
+            return new HotspotNetworkConnectionStatus[size];
         }
     };
 
     @Override
     public String toString() {
-        return new StringBuilder("TetherNetworkConnectionStatus[")
+        return new StringBuilder("HotspotNetworkConnectionStatus[")
                 .append("status=").append(mStatus)
-                .append("tether network=").append(mTetherNetwork.toString())
+                .append("hotspot network=").append(mHotspotNetwork.toString())
                 .append("extras=").append(mExtras.toString())
                 .append("]").toString();
     }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
index 161c83c..d33e08f 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/KnownNetwork.java
@@ -20,15 +20,17 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
+import android.util.ArraySet;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * A data class representing a known Wi-Fi network.
@@ -37,21 +39,28 @@
  */
 @SystemApi
 public final class KnownNetwork implements Parcelable {
+
+    /**
+     * Network source is unknown.
+     */
+    public static final int NETWORK_SOURCE_UNKNOWN = 0;
+
     /**
      * Network is known by a nearby device with the same user account.
      */
-    public static final int NETWORK_SOURCE_NEARBY_SELF = 0;
+    public static final int NETWORK_SOURCE_NEARBY_SELF = 1;
 
     /**
      * Network is known via cloud storage associated with this device's user account.
      */
-    public static final int NETWORK_SOURCE_CLOUD_SELF = 1;
+    public static final int NETWORK_SOURCE_CLOUD_SELF = 2;
 
     /**
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({
+            NETWORK_SOURCE_UNKNOWN,
             NETWORK_SOURCE_NEARBY_SELF,
             NETWORK_SOURCE_CLOUD_SELF
     })
@@ -59,8 +68,8 @@
 
     @NetworkSource private final int mNetworkSource;
     private final String mSsid;
-    @SecurityType private final int[] mSecurityTypes;
-    private final DeviceInfo mDeviceInfo;
+    @SecurityType private final ArraySet<Integer> mSecurityTypes;
+    private final NetworkProviderInfo mNetworkProviderInfo;
 
     /**
      * Builder class for {@link KnownNetwork}.
@@ -68,10 +77,8 @@
     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() {}
+        @SecurityType private final ArraySet<Integer> mSecurityTypes = new ArraySet<>();
+        private NetworkProviderInfo mNetworkProviderInfo;
 
         /**
          * Sets the indicated source of the known network.
@@ -98,26 +105,27 @@
         }
 
         /**
-         * Sets the security types of the known network.
+         * Adds a security type of the known network.
          *
-         * @param securityTypes The array of security types supported by the known network.
+         * @param securityType A security type supported by the known network.
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setSecurityTypes(@NonNull @SecurityType int[] securityTypes) {
-            mSecurityTypes = securityTypes;
+        public Builder addSecurityType(@SecurityType int securityType) {
+            mSecurityTypes.add(securityType);
             return this;
         }
 
         /**
          * Sets the device information of the device providing connectivity.
+         * Must be set if network source is {@link KnownNetwork#NETWORK_SOURCE_NEARBY_SELF}.
          *
-         * @param deviceInfo The device information object.
+         * @param networkProviderInfo The device information object.
          * @return Returns the Builder object.
          */
         @NonNull
-        public Builder setDeviceInfo(@NonNull DeviceInfo deviceInfo) {
-            mDeviceInfo = deviceInfo;
+        public Builder setNetworkProviderInfo(@Nullable NetworkProviderInfo networkProviderInfo) {
+            mNetworkProviderInfo = networkProviderInfo;
             return this;
         }
 
@@ -132,33 +140,39 @@
                     mNetworkSource,
                     mSsid,
                     mSecurityTypes,
-                    mDeviceInfo);
+                    mNetworkProviderInfo);
         }
     }
 
-    private static void validate(int networkSource, String ssid, int [] securityTypes) {
-        if (networkSource != NETWORK_SOURCE_CLOUD_SELF && networkSource
-                != NETWORK_SOURCE_NEARBY_SELF) {
+    private static void validate(int networkSource, String ssid, Set<Integer> securityTypes,
+            NetworkProviderInfo networkProviderInfo) {
+        if (networkSource != NETWORK_SOURCE_UNKNOWN
+                && 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) {
+        if (securityTypes.isEmpty()) {
             throw new IllegalArgumentException("SecurityTypes must be set");
         }
+        if (networkSource == NETWORK_SOURCE_NEARBY_SELF && networkProviderInfo == null) {
+            throw new IllegalArgumentException("Device info must be provided when network source"
+                    + " is NETWORK_SOURCE_NEARBY_SELF");
+        }
     }
 
     private KnownNetwork(
             @NetworkSource int networkSource,
             @NonNull String ssid,
-            @NonNull @SecurityType int[] securityTypes,
-            @NonNull DeviceInfo deviceInfo) {
-        validate(networkSource, ssid, securityTypes);
+            @NonNull @SecurityType ArraySet<Integer> securityTypes,
+            @Nullable NetworkProviderInfo networkProviderInfo) {
+        validate(networkSource, ssid, securityTypes, networkProviderInfo);
         mNetworkSource = networkSource;
         mSsid = ssid;
-        mSecurityTypes = securityTypes;
-        mDeviceInfo = deviceInfo;
+        mSecurityTypes = new ArraySet<>(securityTypes);
+        mNetworkProviderInfo = networkProviderInfo;
     }
 
     /**
@@ -184,22 +198,23 @@
     /**
      * Gets the security types of the known network.
      *
-     * @return Returns the array of security types supported by the known network.
+     * @return Returns a set with security types supported by the known network.
      */
     @NonNull
     @SecurityType
-    public int[] getSecurityTypes() {
+    public Set<Integer> getSecurityTypes() {
         return mSecurityTypes;
     }
 
     /**
      * Gets the device information of the device providing connectivity.
      *
-     * @return Returns the information of the device providing the known network.
+     * @return Returns the information of the device providing the known network. Can be null if the
+     * network source is cloud or unknown.
      */
-    @NonNull
-    public DeviceInfo getDeviceInfo() {
-        return mDeviceInfo;
+    @Nullable
+    public NetworkProviderInfo getNetworkProviderInfo() {
+        return mNetworkProviderInfo;
     }
 
     @Override
@@ -208,14 +223,13 @@
         KnownNetwork other = (KnownNetwork) obj;
         return mNetworkSource == other.getNetworkSource()
                 && Objects.equals(mSsid, other.getSsid())
-                && Arrays.equals(mSecurityTypes, other.getSecurityTypes())
-                && Objects.equals(mDeviceInfo, other.getDeviceInfo());
+                && Objects.equals(mSecurityTypes, other.getSecurityTypes())
+                && Objects.equals(mNetworkProviderInfo, other.getNetworkProviderInfo());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mNetworkSource, mSsid, Arrays.hashCode(mSecurityTypes),
-                mDeviceInfo.hashCode());
+        return Objects.hash(mNetworkSource, mSsid, mSecurityTypes, mNetworkProviderInfo);
     }
 
     @Override
@@ -227,8 +241,8 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mNetworkSource);
         dest.writeString(mSsid);
-        dest.writeIntArray(mSecurityTypes);
-        mDeviceInfo.writeToParcel(dest, flags);
+        dest.writeArraySet(mSecurityTypes);
+        mNetworkProviderInfo.writeToParcel(dest, flags);
     }
 
     /**
@@ -238,8 +252,9 @@
      */
     @NonNull
     public static KnownNetwork readFromParcel(@NonNull Parcel in) {
-        return new KnownNetwork(in.readInt(), in.readString(), in.createIntArray(),
-                DeviceInfo.readFromParcel(in));
+        return new KnownNetwork(in.readInt(), in.readString(),
+                (ArraySet<Integer>) in.readArraySet(null),
+                NetworkProviderInfo.readFromParcel(in));
     }
 
     @NonNull
@@ -260,8 +275,8 @@
         return new StringBuilder("KnownNetwork[")
                 .append("NetworkSource=").append(mNetworkSource)
                 .append(", ssid=").append(mSsid)
-                .append(", securityTypes=").append(Arrays.toString(mSecurityTypes))
-                .append(", deviceInfo=").append(mDeviceInfo.toString())
+                .append(", securityTypes=").append(mSecurityTypes.toString())
+                .append(", networkProviderInfo=").append(mNetworkProviderInfo.toString())
                 .append("]").toString();
     }
 }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
similarity index 95%
copy from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
copy to wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
index 35d5c15..f3cbbc2 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.net.wifi.sharedconnectivity.app;
 
-parcelable DeviceInfo;
\ No newline at end of file
+parcelable NetworkProviderInfo;
\ 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/NetworkProviderInfo.java
similarity index 84%
rename from wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java
rename to wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
index 52abf33..a436571c 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/DeviceInfo.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfo.java
@@ -36,7 +36,7 @@
  * @hide
  */
 @SystemApi
-public final class DeviceInfo implements Parcelable {
+public final class NetworkProviderInfo implements Parcelable {
 
     /**
      * Device type providing connectivity is unknown.
@@ -59,6 +59,16 @@
     public static final int DEVICE_TYPE_LAPTOP = 3;
 
     /**
+     * Device providing connectivity is a watch.
+     */
+    public static final int DEVICE_TYPE_WATCH = 4;
+
+    /**
+     * Device providing connectivity is a watch.
+     */
+    public static final int DEVICE_TYPE_AUTO = 5;
+
+    /**
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
@@ -66,7 +76,9 @@
             DEVICE_TYPE_UNKNOWN,
             DEVICE_TYPE_PHONE,
             DEVICE_TYPE_TABLET,
-            DEVICE_TYPE_LAPTOP
+            DEVICE_TYPE_LAPTOP,
+            DEVICE_TYPE_WATCH,
+            DEVICE_TYPE_AUTO
     })
     public @interface DeviceType {}
 
@@ -77,7 +89,7 @@
     private final int mConnectionStrength;
 
     /**
-     * Builder class for {@link DeviceInfo}.
+     * Builder class for {@link NetworkProviderInfo}.
      */
     public static final class Builder {
         private int mDeviceType;
@@ -149,13 +161,13 @@
         }
 
         /**
-         * Builds the {@link DeviceInfo} object.
+         * Builds the {@link NetworkProviderInfo} object.
          *
-         * @return Returns the built {@link DeviceInfo} object.
+         * @return Returns the built {@link NetworkProviderInfo} object.
          */
         @NonNull
-        public DeviceInfo build() {
-            return new DeviceInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
+        public NetworkProviderInfo build() {
+            return new NetworkProviderInfo(mDeviceType, mDeviceName, mModelName, mBatteryPercentage,
                     mConnectionStrength);
         }
     }
@@ -163,7 +175,8 @@
     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) {
+                && deviceType != DEVICE_TYPE_TABLET && deviceType != DEVICE_TYPE_LAPTOP
+                && deviceType !=  DEVICE_TYPE_WATCH && deviceType != DEVICE_TYPE_AUTO) {
             throw new IllegalArgumentException("Illegal device type");
         }
         if (Objects.isNull(deviceName)) {
@@ -180,7 +193,7 @@
         }
     }
 
-    private DeviceInfo(@DeviceType int deviceType, @NonNull String deviceName,
+    private NetworkProviderInfo(@DeviceType int deviceType, @NonNull String deviceName,
             @NonNull String modelName, int batteryPercentage, int connectionStrength) {
         validate(deviceType, deviceName, modelName, batteryPercentage, connectionStrength);
         mDeviceType = deviceType;
@@ -242,8 +255,8 @@
 
     @Override
     public boolean equals(Object obj) {
-        if (!(obj instanceof DeviceInfo)) return false;
-        DeviceInfo other = (DeviceInfo) obj;
+        if (!(obj instanceof NetworkProviderInfo)) return false;
+        NetworkProviderInfo other = (NetworkProviderInfo) obj;
         return mDeviceType == other.getDeviceType()
                 && Objects.equals(mDeviceName, other.mDeviceName)
                 && Objects.equals(mModelName, other.mModelName)
@@ -271,32 +284,32 @@
     }
 
     /**
-     * Creates a {@link DeviceInfo} object from a parcel.
+     * Creates a {@link NetworkProviderInfo} object from a parcel.
      *
      * @hide
      */
     @NonNull
-    public static DeviceInfo readFromParcel(@NonNull Parcel in) {
-        return new DeviceInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
+    public static NetworkProviderInfo readFromParcel(@NonNull Parcel in) {
+        return new NetworkProviderInfo(in.readInt(), in.readString(), in.readString(), in.readInt(),
                 in.readInt());
     }
 
     @NonNull
-    public static final Creator<DeviceInfo> CREATOR = new Creator<DeviceInfo>() {
+    public static final Creator<NetworkProviderInfo> CREATOR = new Creator<NetworkProviderInfo>() {
         @Override
-        public DeviceInfo createFromParcel(Parcel in) {
+        public NetworkProviderInfo createFromParcel(Parcel in) {
             return readFromParcel(in);
         }
 
         @Override
-        public DeviceInfo[] newArray(int size) {
-            return new DeviceInfo[size];
+        public NetworkProviderInfo[] newArray(int size) {
+            return new NetworkProviderInfo[size];
         }
     };
 
     @Override
     public String toString() {
-        return new StringBuilder("DeviceInfo[")
+        return new StringBuilder("NetworkProviderInfo[")
                 .append("deviceType=").append(mDeviceType)
                 .append(", deviceName=").append(mDeviceName)
                 .append(", modelName=").append(mModelName)
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
index d2b9be7..eb04df6 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityClientCallback.java
@@ -32,14 +32,16 @@
 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.
+     * list of available Hotspot Networks.
+     *
+     * @param networks Updated Hotspot Network list.
      */
-    void onTetherNetworksUpdated(@NonNull List<TetherNetwork> networks);
+    void onHotspotNetworksUpdated(@NonNull List<HotspotNetwork> 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);
@@ -47,20 +49,23 @@
     /**
      * 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);
 
     /**
      * This method is being called by {@link SharedConnectivityService} to notify of a change in the
-     * status of the current tether network connection.
+     * status of the current hotspot network connection.
+     *
      * @param status The new status.
      */
-    void onTetherNetworkConnectionStatusChanged(@NonNull TetherNetworkConnectionStatus status);
+    void onHotspotNetworkConnectionStatusChanged(@NonNull HotspotNetworkConnectionStatus status);
 
     /**
      * This method is being called by {@link SharedConnectivityService} to notify of a change in the
      * status of the current known network connection.
+     *
      * @param status The new status.
      */
     void onKnownNetworkConnectionStatusChanged(@NonNull KnownNetworkConnectionStatus status);
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
index d5d01d3..684b385d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManager.java
@@ -19,6 +19,7 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
@@ -48,7 +49,7 @@
  * 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.
  *
- * The methods {@link #connectTetherNetwork}, {@link #disconnectTetherNetwork},
+ * The methods {@link #connectHotspotNetwork}, {@link #disconnectHotspotNetwork},
  * {@link #connectKnownNetwork} and {@link #forgetKnownNetwork} are not valid and will return false
  * if not called between {@link SharedConnectivityClientCallback#onServiceConnected()}
  * and {@link SharedConnectivityClientCallback#onServiceDisconnected()} or if
@@ -73,12 +74,11 @@
             mCallback = callback;
         }
 
-        @Override
-        public void onTetherNetworksUpdated(@NonNull List<TetherNetwork> networks) {
+        public void onHotspotNetworksUpdated(@NonNull List<HotspotNetwork> networks) {
             if (mCallback != null) {
                 final long token = Binder.clearCallingIdentity();
                 try {
-                    mExecutor.execute(() -> mCallback.onTetherNetworksUpdated(networks));
+                    mExecutor.execute(() -> mCallback.onHotspotNetworksUpdated(networks));
                 } finally {
                     Binder.restoreCallingIdentity(token);
                 }
@@ -110,14 +110,13 @@
             }
         }
 
-        @Override
-        public void onTetherNetworkConnectionStatusChanged(
-                @NonNull TetherNetworkConnectionStatus status) {
+        public void onHotspotNetworkConnectionStatusChanged(
+                @NonNull HotspotNetworkConnectionStatus status) {
             if (mCallback != null) {
                 final long token = Binder.clearCallingIdentity();
                 try {
                     mExecutor.execute(() ->
-                            mCallback.onTetherNetworkConnectionStatusChanged(status));
+                            mCallback.onHotspotNetworkConnectionStatusChanged(status));
                 } finally {
                     Binder.restoreCallingIdentity(token);
                 }
@@ -151,7 +150,7 @@
      * Creates a new instance of {@link SharedConnectivityManager}.
      *
      * Automatically binds to implementation of {@link SharedConnectivityService} specified in
-     * device overlay.
+     * the device overlay.
      *
      * @return An instance of {@link SharedConnectivityManager} or null if the shared connectivity
      * service is not found.
@@ -192,9 +191,9 @@
                 mService = ISharedConnectivityService.Stub.asInterface(service);
                 if (!mCallbackProxyCache.isEmpty()) {
                     synchronized (mCallbackProxyCache) {
-                        mCallbackProxyCache.keySet().forEach(callback -> {
-                            registerCallbackInternal(callback, mCallbackProxyCache.get(callback));
-                        });
+                        mCallbackProxyCache.keySet().forEach(callback ->
+                                registerCallbackInternal(
+                                        callback, mCallbackProxyCache.get(callback)));
                         mCallbackProxyCache.clear();
                     }
                 }
@@ -258,15 +257,18 @@
     }
 
     /**
-     * Registers a callback for receiving updates to the list of Tether Networks and Known Networks.
+     * Registers a callback for receiving updates to the list of Hotspot Networks, Known Networks,
+     * shared connectivity settings state, hotspot network connection status and known network
+     * connection status.
      * The {@link SharedConnectivityClientCallback#onRegisterCallbackFailed} will be called if the
      * registration failed.
      *
      * @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.
+     *                 when the service updates its data.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     public void registerCallback(@NonNull @CallbackExecutor Executor executor,
             @NonNull SharedConnectivityClientCallback callback) {
         Objects.requireNonNull(executor, "executor cannot be null");
@@ -295,6 +297,8 @@
      *
      * @return Returns true if the callback was successfully unregistered, false otherwise.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     public boolean unregisterCallback(
             @NonNull SharedConnectivityClientCallback callback) {
         Objects.requireNonNull(callback, "callback cannot be null");
@@ -323,26 +327,28 @@
         return true;
     }
 
-     /**
+    /**
      * Send command to the implementation of {@link SharedConnectivityService} requesting connection
-     * to the specified Tether Network.
+     * to the specified Hotspot Network.
      *
-     * @param network {@link TetherNetwork} object representing the network the user has requested
+     * @param network {@link HotspotNetwork} 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.
+     * connection was successful.
      */
-    public boolean connectTetherNetwork(@NonNull TetherNetwork network) {
-        Objects.requireNonNull(network, "Tether network cannot be null");
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    public boolean connectHotspotNetwork(@NonNull HotspotNetwork network) {
+        Objects.requireNonNull(network, "Hotspot network cannot be null");
 
         if (mService == null) {
             return false;
         }
 
         try {
-            mService.connectTetherNetwork(network);
+            mService.connectHotspotNetwork(network);
         } catch (RemoteException e) {
-            Log.e(TAG, "Exception in connectTetherNetwork", e);
+            Log.e(TAG, "Exception in connectHotspotNetwork", e);
             return false;
         }
         return true;
@@ -350,22 +356,24 @@
 
     /**
      * Send command to the implementation of {@link SharedConnectivityService} requesting
-     * disconnection from the active Tether Network.
+     * disconnection from the active Hotspot Network.
      *
-     * @param network {@link TetherNetwork} object representing the network the user has requested
+     * @param network {@link HotspotNetwork} object representing the network the user has requested
      *                to disconnect from.
      * @return Returns true if the service received the command. Does not guarantee that the
-     *         disconnection was successful.
+     * disconnection was successful.
      */
-    public boolean disconnectTetherNetwork(@NonNull TetherNetwork network) {
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    public boolean disconnectHotspotNetwork(@NonNull HotspotNetwork network) {
         if (mService == null) {
             return false;
         }
 
         try {
-            mService.disconnectTetherNetwork(network);
+            mService.disconnectHotspotNetwork(network);
         } catch (RemoteException e) {
-            Log.e(TAG, "Exception in disconnectTetherNetwork", e);
+            Log.e(TAG, "Exception in disconnectHotspotNetwork", e);
             return false;
         }
         return true;
@@ -378,8 +386,10 @@
      * @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.
+     * connection was successful.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     public boolean connectKnownNetwork(@NonNull KnownNetwork network) {
         Objects.requireNonNull(network, "Known network cannot be null");
 
@@ -401,8 +411,10 @@
      * 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.
+     * forget action was successful.
      */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
     public boolean forgetKnownNetwork(@NonNull KnownNetwork network) {
         Objects.requireNonNull(network, "Known network cannot be null");
 
@@ -418,4 +430,114 @@
         }
         return true;
     }
+
+    /**
+     * Gets the list of hotspot networks the user can select to connect to.
+     *
+     * @return Returns a {@link List} of {@link HotspotNetwork} objects, empty list on failure.
+     */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    @NonNull
+    public List<HotspotNetwork> getHotspotNetworks() {
+        if (mService == null) {
+            return List.of();
+        }
+
+        try {
+            return mService.getHotspotNetworks();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in getHotspotNetworks", e);
+        }
+        return List.of();
+    }
+
+    /**
+     * Gets the list of known networks the user can select to connect to.
+     *
+     * @return Returns a {@link List} of {@link KnownNetwork} objects, empty list on failure.
+     */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    @NonNull
+    public List<KnownNetwork> getKnownNetworks() {
+        if (mService == null) {
+            return List.of();
+        }
+
+        try {
+            return mService.getKnownNetworks();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in getKnownNetworks", e);
+        }
+        return List.of();
+    }
+
+    /**
+     * Gets the shared connectivity settings state.
+     *
+     * @return Returns a {@link SharedConnectivitySettingsState} object with the state, null on
+     * failure.
+     */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    @Nullable
+    public SharedConnectivitySettingsState getSettingsState() {
+        if (mService == null) {
+            return null;
+        }
+
+        try {
+            return mService.getSettingsState();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in getSettingsState", e);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the connection status of the hotspot network the user selected to connect to.
+     *
+     * @return Returns a {@link HotspotNetworkConnectionStatus} object with the connection status,
+     * null on failure. If no connection is active the status will be
+     * {@link HotspotNetworkConnectionStatus#CONNECTION_STATUS_UNKNOWN}.
+     */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    @Nullable
+    public HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus() {
+        if (mService == null) {
+            return null;
+        }
+
+        try {
+            return mService.getHotspotNetworkConnectionStatus();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in getHotspotNetworkConnectionStatus", e);
+        }
+        return null;
+    }
+
+    /**
+     * Gets the connection status of the known network the user selected to connect to.
+     *
+     * @return Returns a {@link KnownNetworkConnectionStatus} object with the connection status,
+     * null on failure. If no connection is active the status will be
+     * {@link KnownNetworkConnectionStatus#CONNECTION_STATUS_UNKNOWN}.
+     */
+    @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_SETUP_WIZARD})
+    @Nullable
+    public KnownNetworkConnectionStatus getKnownNetworkConnectionStatus() {
+        if (mService == null) {
+            return null;
+        }
+
+        try {
+            return mService.getKnownNetworkConnectionStatus();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Exception in getKnownNetworkConnectionStatus", e);
+        }
+        return null;
+    }
 }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl
deleted file mode 100644
index 6cc4cfe..0000000
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetwork.aidl
+++ /dev/null
@@ -1,19 +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 android.net.wifi.sharedconnectivity.app;
-
-parcelable TetherNetwork;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl
deleted file mode 100644
index c677a6c..0000000
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatus.aidl
+++ /dev/null
@@ -1,19 +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 android.net.wifi.sharedconnectivity.app;
-
-parcelable TetherNetworkConnectionStatus;
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
index 6f6f162..737aa6d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityCallback.aidl
@@ -19,15 +19,15 @@
 import android.net.wifi.sharedconnectivity.app.KnownNetwork;
 import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
 
 /*
  * @hide
  */
 interface ISharedConnectivityCallback {
-    oneway void onTetherNetworksUpdated(in List<TetherNetwork> networks);
-    oneway void onTetherNetworkConnectionStatusChanged(in TetherNetworkConnectionStatus status);
+    oneway void onHotspotNetworksUpdated(in List<HotspotNetwork> networks);
+    oneway void onHotspotNetworkConnectionStatusChanged(in HotspotNetworkConnectionStatus status);
     oneway void onKnownNetworksUpdated(in List<KnownNetwork> networks);
     oneway void onKnownNetworkConnectionStatusChanged(in KnownNetworkConnectionStatus status);
     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
index 52da596..c81380d 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/ISharedConnectivityService.aidl
@@ -17,7 +17,10 @@
 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.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.service.ISharedConnectivityCallback;
 
 /*
@@ -26,8 +29,13 @@
 interface ISharedConnectivityService {
     void registerCallback(in ISharedConnectivityCallback callback);
     void unregisterCallback(in ISharedConnectivityCallback callback);
-    void connectTetherNetwork(in TetherNetwork network);
-    void disconnectTetherNetwork(in TetherNetwork network);
+    void connectHotspotNetwork(in HotspotNetwork network);
+    void disconnectHotspotNetwork(in HotspotNetwork network);
     void connectKnownNetwork(in KnownNetwork network);
     void forgetKnownNetwork(in KnownNetwork network);
+    List<HotspotNetwork> getHotspotNetworks();
+    List<KnownNetwork> getKnownNetworks();
+    SharedConnectivitySettingsState getSettingsState();
+    HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus();
+    KnownNetworkConnectionStatus getKnownNetworkConnectionStatus();
 }
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
index b751f1e..c53da9c 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
@@ -27,22 +27,21 @@
 import android.app.Service;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.app.KnownNetwork;
 import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.app.SharedConnectivityManager;
 import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.RemoteCallbackList;
 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;
 
 
 /**
@@ -61,30 +60,21 @@
     private static final boolean DEBUG = true;
 
     private 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 final RemoteCallbackList<ISharedConnectivityCallback> mRemoteCallbackList =
+            new RemoteCallbackList<>();
+    private List<HotspotNetwork> mHotspotNetworks = Collections.emptyList();
     private List<KnownNetwork> mKnownNetworks = Collections.emptyList();
-    private SharedConnectivitySettingsState mSettingsState;
-    private TetherNetworkConnectionStatus mTetherNetworkConnectionStatus;
-    private KnownNetworkConnectionStatus mKnownNetworkConnectionStatus;
-
-    private final class DeathRecipient implements IBinder.DeathRecipient {
-        ISharedConnectivityCallback mCallback;
-
-        DeathRecipient(ISharedConnectivityCallback callback) {
-            mCallback = callback;
-        }
-
-        @Override
-        public void binderDied() {
-            mCallbacks.remove(mCallback);
-            mDeathRecipientMap.remove(mCallback);
-        }
-    }
+    private SharedConnectivitySettingsState mSettingsState =
+            new SharedConnectivitySettingsState.Builder().setInstantTetherEnabled(false)
+                    .setExtras(Bundle.EMPTY).build();
+    private HotspotNetworkConnectionStatus mHotspotNetworkConnectionStatus =
+            new HotspotNetworkConnectionStatus.Builder()
+                    .setStatus(HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN)
+                    .setExtras(Bundle.EMPTY).build();
+    private KnownNetworkConnectionStatus mKnownNetworkConnectionStatus =
+            new KnownNetworkConnectionStatus.Builder()
+                    .setStatus(KnownNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN)
+                    .setExtras(Bundle.EMPTY).build();
 
     @Override
     @Nullable
@@ -92,42 +82,153 @@
         if (DEBUG) Log.i(TAG, "onBind intent=" + intent);
         mHandler = new Handler(getMainLooper());
         IBinder serviceStub = new ISharedConnectivityService.Stub() {
+
+            /**
+             * Registers a callback for receiving updates to the list of Hotspot Networks, Known
+             * Networks, shared connectivity settings state, hotspot network connection status and
+             * known network connection status.
+             *
+             * @param callback The callback of type {@link ISharedConnectivityCallback} to be called
+             *                 when there is update to the data.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
             public void registerCallback(ISharedConnectivityCallback callback) {
                 checkPermissions();
                 mHandler.post(() -> onRegisterCallback(callback));
             }
 
+            /**
+             * Unregisters a previously registered callback.
+             *
+             * @param callback The callback to unregister.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
             public void unregisterCallback(ISharedConnectivityCallback callback) {
                 checkPermissions();
                 mHandler.post(() -> onUnregisterCallback(callback));
             }
 
+            /**
+             * Connects to a hotspot network.
+             *
+             * @param network The network to connect to.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
-            public void connectTetherNetwork(TetherNetwork network) {
+            public void connectHotspotNetwork(HotspotNetwork network) {
                 checkPermissions();
-                mHandler.post(() -> onConnectTetherNetwork(network));
+                mHandler.post(() -> onConnectHotspotNetwork(network));
             }
 
-            @Override
-            public void disconnectTetherNetwork(TetherNetwork network) {
+            /**
+             * Disconnects from a previously connected hotspot network.
+             *
+             * @param network The network to disconnect from.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
+            public void disconnectHotspotNetwork(HotspotNetwork network) {
                 checkPermissions();
-                mHandler.post(() -> onDisconnectTetherNetwork(network));
+                mHandler.post(() -> onDisconnectHotspotNetwork(network));
             }
 
+            /**
+             * Adds a known network to the available networks on the device and connects to it.
+             *
+             * @param network The network to connect to.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
             @Override
             public void connectKnownNetwork(KnownNetwork network) {
                 checkPermissions();
                 mHandler.post(() -> onConnectKnownNetwork(network));
             }
 
+            /**
+             * Removes a known network from the available networks on the device which will also
+             * disconnect the device from the network if it is connected to it.
+             *
+             * @param network The network to forget.
+             */
             @Override
             public void forgetKnownNetwork(KnownNetwork network) {
                 checkPermissions();
                 mHandler.post(() -> onForgetKnownNetwork(network));
             }
 
+            /**
+             * Gets the list of hotspot networks the user can select to connect to.
+             *
+             * @return Returns a {@link List} of {@link HotspotNetwork} objects
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
+            @Override
+            public List<HotspotNetwork> getHotspotNetworks() {
+                checkPermissions();
+                return mHotspotNetworks;
+            }
+
+            /**
+             * Gets the list of known networks the user can select to connect to.
+             *
+             * @return Returns a {@link List} of {@link KnownNetwork} objects.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
+            @Override
+            public List<KnownNetwork> getKnownNetworks() {
+                checkPermissions();
+                return mKnownNetworks;
+            }
+
+            /**
+             * Gets the shared connectivity settings state.
+             *
+             * @return Returns a {@link SharedConnectivitySettingsState} object with the state.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
+            @Override
+            public SharedConnectivitySettingsState getSettingsState() {
+                checkPermissions();
+                return mSettingsState;
+            }
+
+            /**
+             * Gets the connection status of the hotspot network the user selected to connect to.
+             *
+             * @return Returns a {@link HotspotNetworkConnectionStatus} object with the connection
+             * status.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
+            @Override
+            public HotspotNetworkConnectionStatus getHotspotNetworkConnectionStatus() {
+                checkPermissions();
+                return mHotspotNetworkConnectionStatus;
+            }
+
+            /**
+             * Gets the connection status of the known network the user selected to connect to.
+             *
+             * @return Returns a {@link KnownNetworkConnectionStatus} object with the connection
+             * status.
+             */
+            @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
+                    android.Manifest.permission.NETWORK_SETUP_WIZARD})
+            @Override
+            public KnownNetworkConnectionStatus getKnownNetworkConnectionStatus() {
+                checkPermissions();
+                return mKnownNetworkConnectionStatus;
+            }
+
             @RequiresPermission(anyOf = {android.Manifest.permission.NETWORK_SETTINGS,
                     android.Manifest.permission.NETWORK_SETUP_WIZARD})
             /**
@@ -152,103 +253,38 @@
 
     /** @hide */
     @TestApi
-    public void onBind() {}
+    public void onBind() {
+    }
 
     private void onRegisterCallback(ISharedConnectivityCallback callback) {
-        // Listener gets triggered on first register using cashed data
-        if (!notifyTetherNetworkUpdate(callback) || !notifyKnownNetworkUpdate(callback)
-                || !notifySettingsStateUpdate(callback)
-                || !notifyTetherNetworkConnectionStatusChanged(callback)
-                || !notifyKnownNetworkConnectionStatusChanged(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);
-        }
+        mRemoteCallbackList.register(callback);
     }
 
     private void onUnregisterCallback(ISharedConnectivityCallback callback) {
-        DeathRecipient deathRecipient = mDeathRecipientMap.get(callback);
-        if (deathRecipient != null) {
-            callback.asBinder().unlinkToDeath(deathRecipient, 0);
-            mDeathRecipientMap.remove(callback);
-        }
-        mCallbacks.remove(callback);
+        mRemoteCallbackList.unregister(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;
-    }
-
-    private boolean notifyTetherNetworkConnectionStatusChanged(
-            ISharedConnectivityCallback callback) {
-        try {
-            callback.onTetherNetworkConnectionStatusChanged(mTetherNetworkConnectionStatus);
-        } catch (RemoteException e) {
-            if (DEBUG) Log.w(TAG, "Exception in notifyTetherNetworkConnectionStatusChanged", e);
-            return false;
-        }
-        return true;
-    }
-
-    private boolean notifyKnownNetworkConnectionStatusChanged(
-            ISharedConnectivityCallback callback) {
-        try {
-            callback.onKnownNetworkConnectionStatusChanged(mKnownNetworkConnectionStatus);
-        } catch (RemoteException e) {
-            if (DEBUG) Log.w(TAG, "Exception in notifyKnownNetworkConnectionStatusChanged", e);
-            return false;
-        }
-        return true;
-    }
     /**
-     * Implementing application should call this method to provide an up-to-date list of Tether
+     * Implementing application should call this method to provide an up-to-date list of Hotspot
      * 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.
+     * @param networks The updated list of {@link HotspotNetwork} objects.
      */
-    public final void setTetherNetworks(@NonNull List<TetherNetwork> networks) {
-        mTetherNetworks = networks;
+    public final void setHotspotNetworks(@NonNull List<HotspotNetwork> networks) {
+        mHotspotNetworks = networks;
 
-        for (ISharedConnectivityCallback callback:mCallbacks) {
-            notifyTetherNetworkUpdate(callback);
+        int count = mRemoteCallbackList.beginBroadcast();
+        for (int i = 0; i < count; i++) {
+            try {
+                mRemoteCallbackList.getBroadcastItem(i).onHotspotNetworksUpdated(mHotspotNetworks);
+            } catch (RemoteException e) {
+                if (DEBUG) Log.w(TAG, "Exception in setHotspotNetworks", e);
+            }
         }
+        mRemoteCallbackList.finishBroadcast();
     }
 
     /**
@@ -263,9 +299,15 @@
     public final void setKnownNetworks(@NonNull List<KnownNetwork> networks) {
         mKnownNetworks = networks;
 
-        for (ISharedConnectivityCallback callback:mCallbacks) {
-            notifyKnownNetworkUpdate(callback);
+        int count = mRemoteCallbackList.beginBroadcast();
+        for (int i = 0; i < count; i++) {
+            try {
+                mRemoteCallbackList.getBroadcastItem(i).onKnownNetworksUpdated(mKnownNetworks);
+            } catch (RemoteException e) {
+                if (DEBUG) Log.w(TAG, "Exception in setKnownNetworks", e);
+            }
         }
+        mRemoteCallbackList.finishBroadcast();
     }
 
     /**
@@ -276,29 +318,44 @@
      * that are inaccessible will be unregistered.
      *
      * @param settingsState The updated state {@link SharedConnectivitySettingsState}
-     *                 objects.
+     *                      objects.
      */
     public final void setSettingsState(@NonNull SharedConnectivitySettingsState settingsState) {
         mSettingsState = settingsState;
 
-        for (ISharedConnectivityCallback callback:mCallbacks) {
-            notifySettingsStateUpdate(callback);
+        int count = mRemoteCallbackList.beginBroadcast();
+        for (int i = 0; i < count; i++) {
+            try {
+                mRemoteCallbackList.getBroadcastItem(i).onSharedConnectivitySettingsChanged(
+                        mSettingsState);
+            } catch (RemoteException e) {
+                if (DEBUG) Log.w(TAG, "Exception in setSettingsState", e);
+            }
         }
+        mRemoteCallbackList.finishBroadcast();
     }
 
     /**
      * Implementing application should call this method to provide an up-to-date status of enabling
-     * and connecting to the tether network.
+     * and connecting to the hotspot network.
      *
-     * @param status The updated status {@link TetherNetworkConnectionStatus} of the connection.
-     *
+     * @param status The updated status {@link HotspotNetworkConnectionStatus} of the connection.
      */
-    public final void updateTetherNetworkConnectionStatus(
-            @NonNull TetherNetworkConnectionStatus status) {
-        mTetherNetworkConnectionStatus = status;
-        for (ISharedConnectivityCallback callback:mCallbacks) {
-            notifyTetherNetworkConnectionStatusChanged(callback);
+    public final void updateHotspotNetworkConnectionStatus(
+            @NonNull HotspotNetworkConnectionStatus status) {
+        mHotspotNetworkConnectionStatus = status;
+
+        int count = mRemoteCallbackList.beginBroadcast();
+        for (int i = 0; i < count; i++) {
+            try {
+                mRemoteCallbackList
+                        .getBroadcastItem(i).onHotspotNetworkConnectionStatusChanged(
+                                mHotspotNetworkConnectionStatus);
+            } catch (RemoteException e) {
+                if (DEBUG) Log.w(TAG, "Exception in updateHotspotNetworkConnectionStatus", e);
+            }
         }
+        mRemoteCallbackList.finishBroadcast();
     }
 
     /**
@@ -306,34 +363,41 @@
      * connecting to a known network.
      *
      * @param status The updated status {@link KnownNetworkConnectionStatus} of the connection.
-     *
      */
     public final void updateKnownNetworkConnectionStatus(
             @NonNull KnownNetworkConnectionStatus status) {
         mKnownNetworkConnectionStatus = status;
 
-        for (ISharedConnectivityCallback callback:mCallbacks) {
-            notifyKnownNetworkConnectionStatusChanged(callback);
+        int count = mRemoteCallbackList.beginBroadcast();
+        for (int i = 0; i < count; i++) {
+            try {
+                mRemoteCallbackList
+                        .getBroadcastItem(i).onKnownNetworkConnectionStatusChanged(
+                                mKnownNetworkConnectionStatus);
+            } catch (RemoteException e) {
+                if (DEBUG) Log.w(TAG, "Exception in updateKnownNetworkConnectionStatus", e);
+            }
         }
+        mRemoteCallbackList.finishBroadcast();
     }
 
     /**
      * Implementing application should implement this method.
      *
-     * Implementation should initiate a connection to the Tether Network indicated.
+     * Implementation should initiate a connection to the Hotspot Network indicated.
      *
-     * @param network Object identifying the Tether Network the user has requested a connection to.
+     * @param network Object identifying the Hotspot Network the user has requested a connection to.
      */
-    public abstract void onConnectTetherNetwork(@NonNull TetherNetwork network);
+    public abstract void onConnectHotspotNetwork(@NonNull HotspotNetwork network);
 
     /**
      * Implementing application should implement this method.
      *
-     * Implementation should initiate a disconnection from the active Tether Network.
+     * Implementation should initiate a disconnection from the active Hotspot Network.
      *
-     * @param network Object identifying the Tether Network the user has requested to disconnect.
+     * @param network Object identifying the Hotspot Network the user has requested to disconnect.
      */
-    public abstract void onDisconnectTetherNetwork(@NonNull TetherNetwork network);
+    public abstract void onDisconnectHotspotNetwork(@NonNull HotspotNetwork network);
 
     /**
      * Implementing application should implement this method.
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java
deleted file mode 100644
index f8f0700..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/DeviceInfoTest.java
+++ /dev/null
@@ -1,116 +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 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/HotspotNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.java
new file mode 100644
index 0000000..1f76b48
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkConnectionStatusTest.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_WEP;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link HotspotNetworkConnectionStatus}.
+ */
+@SmallTest
+public class HotspotNetworkConnectionStatusTest {
+    private static final long DEVICE_ID = 11L;
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.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 String BUNDLE_KEY = "INT-KEY";
+    private static final int BUNDLE_VALUE = 1;
+
+    /**
+     * Verifies parcel serialization/deserialization.
+     */
+    @Test
+    public void testParcelOperation() {
+        HotspotNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
+
+        Parcel parcelW = Parcel.obtain();
+        status.writeToParcel(parcelW, 0);
+        byte[] bytes = parcelW.marshall();
+        parcelW.recycle();
+
+        Parcel parcelR = Parcel.obtain();
+        parcelR.unmarshall(bytes, 0, bytes.length);
+        parcelR.setDataPosition(0);
+        HotspotNetworkConnectionStatus fromParcel =
+                HotspotNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
+
+        assertThat(fromParcel).isEqualTo(status);
+        assertThat(fromParcel.hashCode()).isEqualTo(status.hashCode());
+    }
+
+    /**
+     * Verifies the Equals operation
+     */
+    @Test
+    public void testEqualsOperation() {
+        HotspotNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+        HotspotNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+        assertThat(status1).isEqualTo(status2);
+
+        HotspotNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
+                .setStatus(CONNECTION_STATUS_TETHERING_TIMEOUT);
+        assertThat(builder.build()).isNotEqualTo(status1);
+
+        builder = buildConnectionStatusBuilder()
+                .setHotspotNetwork(buildHotspotNetworkBuilder().setDeviceId(DEVICE_ID_1).build());
+        assertThat(builder.build()).isNotEqualTo(status1);
+    }
+
+    /**
+     * Verifies the get methods return the expected data.
+     */
+    @Test
+    public void testGetMethods() {
+        HotspotNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
+        assertThat(status.getStatus()).isEqualTo(CONNECTION_STATUS_ENABLING_HOTSPOT);
+        assertThat(status.getHotspotNetwork()).isEqualTo(buildHotspotNetworkBuilder().build());
+        assertThat(status.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
+    }
+
+    @Test
+    public void testHashCode() {
+        HotspotNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+        HotspotNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+
+        assertThat(status1.hashCode()).isEqualTo(status2.hashCode());
+    }
+
+    private HotspotNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
+        return new HotspotNetworkConnectionStatus.Builder()
+                .setStatus(CONNECTION_STATUS_ENABLING_HOTSPOT)
+                .setHotspotNetwork(buildHotspotNetworkBuilder().build())
+                .setExtras(buildBundle());
+    }
+
+    private Bundle buildBundle() {
+        Bundle bundle = new Bundle();
+        bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
+        return bundle;
+    }
+
+    private HotspotNetwork.Builder buildHotspotNetworkBuilder() {
+        HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
+                .setDeviceId(DEVICE_ID)
+                .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+                .setHostNetworkType(NETWORK_TYPE)
+                .setNetworkName(NETWORK_NAME)
+                .setHotspotSsid(HOTSPOT_SSID)
+                .setHotspotBssid(HOTSPOT_BSSID);
+        Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
+        return builder;
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
new file mode 100644
index 0000000..b769270
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/HotspotNetworkTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES 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.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetwork.NETWORK_TYPE_WIFI;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+
+/**
+ * Unit tests for {@link HotspotNetwork}.
+ */
+@SmallTest
+public class HotspotNetworkTest {
+    private static final long DEVICE_ID = 11L;
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.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 NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
+            new NetworkProviderInfo.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() {
+        HotspotNetwork network = buildHotspotNetworkBuilder().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);
+        HotspotNetwork fromParcel = HotspotNetwork.CREATOR.createFromParcel(parcelR);
+
+        assertThat(fromParcel).isEqualTo(network);
+        assertThat(fromParcel.hashCode()).isEqualTo(network.hashCode());
+    }
+
+    /**
+     * Verifies the Equals operation
+     */
+    @Test
+    public void testEqualsOperation() {
+        HotspotNetwork network1 = buildHotspotNetworkBuilder().build();
+        HotspotNetwork network2 = buildHotspotNetworkBuilder().build();
+        assertThat(network1).isEqualTo(network2);
+
+        HotspotNetwork.Builder builder = buildHotspotNetworkBuilder().setDeviceId(DEVICE_ID_1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder().setNetworkProviderInfo(NETWORK_PROVIDER_INFO1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder().setHostNetworkType(NETWORK_TYPE_1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder().setNetworkName(NETWORK_NAME_1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder().setHotspotSsid(HOTSPOT_SSID_1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder().setHotspotBssid(HOTSPOT_BSSID_1);
+        assertThat(builder.build()).isNotEqualTo(network1);
+
+        builder = buildHotspotNetworkBuilder();
+        HotspotNetwork.Builder builder1 = buildHotspotNetworkBuilder();
+        Arrays.stream(HOTSPOT_SECURITY_TYPES_1).forEach(builder1::addHotspotSecurityType);
+
+        assertThat(builder1.build()).isNotEqualTo(builder.build());
+    }
+
+    /**
+     * Verifies the get methods return the expected data.
+     */
+    @Test
+    public void testGetMethods() {
+        HotspotNetwork network = buildHotspotNetworkBuilder().build();
+        ArraySet<Integer> securityTypes = new ArraySet<>();
+        Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(securityTypes::add);
+
+        assertThat(network.getDeviceId()).isEqualTo(DEVICE_ID);
+        assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
+        assertThat(network.getHostNetworkType()).isEqualTo(NETWORK_TYPE);
+        assertThat(network.getNetworkName()).isEqualTo(NETWORK_NAME);
+        assertThat(network.getHotspotSsid()).isEqualTo(HOTSPOT_SSID);
+        assertThat(network.getHotspotBssid()).isEqualTo(HOTSPOT_BSSID);
+        assertThat(network.getHotspotSecurityTypes()).containsExactlyElementsIn(securityTypes);
+    }
+
+    @Test
+    public void testHashCode() {
+        HotspotNetwork network1 = buildHotspotNetworkBuilder().build();
+        HotspotNetwork network2 = buildHotspotNetworkBuilder().build();
+
+        assertThat(network1.hashCode()).isEqualTo(network2.hashCode());
+    }
+
+    private HotspotNetwork.Builder buildHotspotNetworkBuilder() {
+        HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
+                .setDeviceId(DEVICE_ID)
+                .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+                .setHostNetworkType(NETWORK_TYPE)
+                .setNetworkName(NETWORK_NAME)
+                .setHotspotSsid(HOTSPOT_SSID)
+                .setHotspotBssid(HOTSPOT_BSSID);
+        Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
+        return builder;
+    }
+}
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
index 37dca8d..2a6046f 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkConnectionStatusTest.java
@@ -17,13 +17,12 @@
 package android.net.wifi.sharedconnectivity.app;
 
 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.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED;
 import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVE_FAILED;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Bundle;
 import android.os.Parcel;
@@ -32,19 +31,24 @@
 
 import org.junit.Test;
 
+import java.util.Arrays;
+
 /**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus}.
+ * Unit tests for {@link KnownNetworkConnectionStatus}.
  */
 @SmallTest
 public class KnownNetworkConnectionStatusTest {
     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 NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.Builder()
+                    .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName(
+                            "TEST_MODEL")
+                    .setConnectionStrength(2).setBatteryPercentage(50).build();
     private static final String SSID_1 = "TEST_SSID1";
     private static final String BUNDLE_KEY = "INT-KEY";
+    private static final int BUNDLE_VALUE = 1;
 
     /**
      * Verifies parcel serialization/deserialization.
@@ -64,8 +68,8 @@
         KnownNetworkConnectionStatus fromParcel =
                 KnownNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
 
-        assertEquals(status, fromParcel);
-        assertEquals(status.hashCode(), fromParcel.hashCode());
+        assertThat(fromParcel).isEqualTo(status);
+        assertThat(fromParcel.hashCode()).isEqualTo(status.hashCode());
     }
 
     /**
@@ -75,15 +79,15 @@
     public void testEqualsOperation() {
         KnownNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
         KnownNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
-        assertEquals(status2, status2);
+        assertThat(status1).isEqualTo(status2);
 
         KnownNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
                 .setStatus(CONNECTION_STATUS_SAVE_FAILED);
-        assertNotEquals(status1, builder.build());
+        assertThat(builder.build()).isNotEqualTo(status1);
 
         builder = buildConnectionStatusBuilder()
                 .setKnownNetwork(buildKnownNetworkBuilder().setSsid(SSID_1).build());
-        assertNotEquals(status1, builder.build());
+        assertThat(builder.build()).isNotEqualTo(status1);
     }
 
     /**
@@ -92,9 +96,17 @@
     @Test
     public void testGetMethods() {
         KnownNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
-        assertEquals(status.getStatus(), CONNECTION_STATUS_SAVED);
-        assertEquals(status.getKnownNetwork(), buildKnownNetworkBuilder().build());
-        assertEquals(status.getExtras().getInt(BUNDLE_KEY), buildBundle().getInt(BUNDLE_KEY));
+        assertThat(status.getStatus()).isEqualTo(CONNECTION_STATUS_SAVED);
+        assertThat(status.getKnownNetwork()).isEqualTo(buildKnownNetworkBuilder().build());
+        assertThat(status.getExtras().getInt(BUNDLE_KEY)).isEqualTo(BUNDLE_VALUE);
+    }
+
+    @Test
+    public void testHashCode() {
+        KnownNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
+        KnownNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
+
+        assertThat(status1.hashCode()).isEqualTo(status2.hashCode());
     }
 
     private KnownNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
@@ -106,13 +118,15 @@
 
     private Bundle buildBundle() {
         Bundle bundle = new Bundle();
-        bundle.putInt(BUNDLE_KEY, 1);
+        bundle.putInt(BUNDLE_KEY, BUNDLE_VALUE);
         return bundle;
     }
 
     private KnownNetwork.Builder buildKnownNetworkBuilder() {
-        return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
-                .setSecurityTypes(SECURITY_TYPES).setDeviceInfo(DEVICE_INFO);
+        KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+                .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+        Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
+        return builder;
     }
 
 }
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
index 266afcc..1b9a7eb 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/KnownNetworkTest.java
@@ -18,23 +18,24 @@
 
 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 android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
 
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Parcel;
+import android.util.ArraySet;
 
 import androidx.test.filters.SmallTest;
 
 import org.junit.Test;
 
+import java.util.Arrays;
+
 /**
- * Unit tests for {@link android.app.sharedconnectivity.KnownNetwork}.
+ * Unit tests for {@link KnownNetwork}.
  */
 @SmallTest
 public class KnownNetworkTest {
@@ -42,15 +43,17 @@
     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 NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.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();
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO1 =
+            new NetworkProviderInfo.Builder().setDeviceType(DEVICE_TYPE_PHONE)
+                    .setDeviceName("TEST_NAME_1").setModelName("TEST_MODEL_1")
+                    .setConnectionStrength(3).setBatteryPercentage(33).build();
 
     /**
      * Verifies parcel serialization/deserialization.
@@ -69,8 +72,8 @@
         parcelR.setDataPosition(0);
         KnownNetwork fromParcel = KnownNetwork.CREATOR.createFromParcel(parcelR);
 
-        assertEquals(network, fromParcel);
-        assertEquals(network.hashCode(), fromParcel.hashCode());
+        assertThat(fromParcel).isEqualTo(network);
+        assertThat(fromParcel.hashCode()).isEqualTo(network.hashCode());
     }
 
     /**
@@ -80,20 +83,21 @@
     public void testEqualsOperation() {
         KnownNetwork network1 = buildKnownNetworkBuilder().build();
         KnownNetwork network2 = buildKnownNetworkBuilder().build();
-        assertEquals(network1, network2);
+        assertThat(network1).isEqualTo(network2);
 
         KnownNetwork.Builder builder = buildKnownNetworkBuilder()
                 .setNetworkSource(NETWORK_SOURCE_1);
-        assertNotEquals(network1, builder.build());
+        assertThat(builder.build()).isNotEqualTo(network1);
 
         builder = buildKnownNetworkBuilder().setSsid(SSID_1);
-        assertNotEquals(network1, builder.build());
+        assertThat(builder.build()).isNotEqualTo(network1);
 
-        builder = buildKnownNetworkBuilder().setSecurityTypes(SECURITY_TYPES_1);
-        assertNotEquals(network1, builder.build());
+        builder = buildKnownNetworkBuilder();
+        Arrays.stream(SECURITY_TYPES_1).forEach(builder::addSecurityType);
+        assertThat(builder.build()).isNotEqualTo(network1);
 
-        builder = buildKnownNetworkBuilder().setDeviceInfo(DEVICE_INFO_1);
-        assertNotEquals(network1, builder.build());
+        builder = buildKnownNetworkBuilder().setNetworkProviderInfo(NETWORK_PROVIDER_INFO1);
+        assertThat(builder.build()).isNotEqualTo(network1);
     }
 
     /**
@@ -102,14 +106,27 @@
     @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);
+        ArraySet<Integer> securityTypes = new ArraySet<>();
+        Arrays.stream(SECURITY_TYPES).forEach(securityTypes::add);
+
+        assertThat(network.getNetworkSource()).isEqualTo(NETWORK_SOURCE);
+        assertThat(network.getSsid()).isEqualTo(SSID);
+        assertThat(network.getSecurityTypes()).containsExactlyElementsIn(securityTypes);
+        assertThat(network.getNetworkProviderInfo()).isEqualTo(NETWORK_PROVIDER_INFO);
+    }
+
+    @Test
+    public void testHashCode() {
+        KnownNetwork network1 = buildKnownNetworkBuilder().build();
+        KnownNetwork network2 = buildKnownNetworkBuilder().build();
+
+        assertThat(network1.hashCode()).isEqualTo(network2.hashCode());
     }
 
     private KnownNetwork.Builder buildKnownNetworkBuilder() {
-        return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
-                .setSecurityTypes(SECURITY_TYPES).setDeviceInfo(DEVICE_INFO);
+        KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+                .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+        Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
+        return builder;
     }
 }
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.java
new file mode 100644
index 0000000..5de6544
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/NetworkProviderInfoTest.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 android.net.wifi.sharedconnectivity.app;
+
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_LAPTOP;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_PHONE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link NetworkProviderInfo}.
+ */
+@SmallTest
+public class NetworkProviderInfoTest {
+
+    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() {
+        NetworkProviderInfo info = buildNetworkProviderInfoBuilder().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);
+        NetworkProviderInfo fromParcel = NetworkProviderInfo.CREATOR.createFromParcel(parcelR);
+
+        assertThat(fromParcel).isEqualTo(info);
+        assertThat(fromParcel.hashCode()).isEqualTo(info.hashCode());
+    }
+
+    /**
+     * Verifies the Equals operation
+     */
+    @Test
+    public void testEqualsOperation() {
+        NetworkProviderInfo info1 = buildNetworkProviderInfoBuilder().build();
+        NetworkProviderInfo info2 = buildNetworkProviderInfoBuilder().build();
+        assertThat(info1).isEqualTo(info2);
+
+        NetworkProviderInfo.Builder builder = buildNetworkProviderInfoBuilder().setDeviceType(
+                DEVICE_TYPE_1);
+        assertThat(builder.build()).isNotEqualTo(info1);
+
+        builder = buildNetworkProviderInfoBuilder().setDeviceName(DEVICE_NAME_1);
+        assertThat(builder.build()).isNotEqualTo(info1);
+
+        builder = buildNetworkProviderInfoBuilder().setModelName(DEVICE_MODEL_1);
+        assertThat(builder.build()).isNotEqualTo(info1);
+
+        builder = buildNetworkProviderInfoBuilder()
+                .setBatteryPercentage(BATTERY_PERCENTAGE_1);
+        assertThat(builder.build()).isNotEqualTo(info1);
+
+        builder = buildNetworkProviderInfoBuilder()
+                .setConnectionStrength(CONNECTION_STRENGTH_1);
+        assertThat(builder.build()).isNotEqualTo(info1);
+    }
+
+    /**
+     * Verifies the get methods return the expected data.
+     */
+    @Test
+    public void testGetMethods() {
+        NetworkProviderInfo info = buildNetworkProviderInfoBuilder().build();
+        assertThat(info.getDeviceType()).isEqualTo(DEVICE_TYPE);
+        assertThat(info.getDeviceName()).isEqualTo(DEVICE_NAME);
+        assertThat(info.getModelName()).isEqualTo(DEVICE_MODEL);
+        assertThat(info.getBatteryPercentage()).isEqualTo(BATTERY_PERCENTAGE);
+        assertThat(info.getConnectionStrength()).isEqualTo(CONNECTION_STRENGTH);
+    }
+
+    @Test
+    public void testHashCode() {
+        NetworkProviderInfo info1 = buildNetworkProviderInfoBuilder().build();
+        NetworkProviderInfo info2 = buildNetworkProviderInfoBuilder().build();
+
+        assertThat(info1.hashCode()).isEqualTo(info2.hashCode());
+    }
+
+    private NetworkProviderInfo.Builder buildNetworkProviderInfoBuilder() {
+        return new NetworkProviderInfo.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/SharedConnectivityManagerTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
index 439d456..9fc352c 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivityManagerTest.java
@@ -18,13 +18,12 @@
 
 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.HotspotNetwork.NETWORK_TYPE_CELLULAR;
 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 android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doThrow;
@@ -36,6 +35,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.net.wifi.sharedconnectivity.service.ISharedConnectivityService;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.RemoteException;
 
@@ -46,6 +46,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.Executor;
 
 /**
@@ -54,9 +56,11 @@
 @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 NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.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";
@@ -70,13 +74,16 @@
     private static final String SERVICE_INTENT_ACTION = "TEST_INTENT_ACTION";
 
 
-    @Mock Context mContext;
+    @Mock
+    Context mContext;
     @Mock
     ISharedConnectivityService mService;
-    @Mock Executor mExecutor;
+    @Mock
+    Executor mExecutor;
     @Mock
     SharedConnectivityClientCallback mClientCallback;
-    @Mock Resources mResources;
+    @Mock
+    Resources mResources;
     @Mock
     ISharedConnectivityService.Stub mIBinder;
 
@@ -95,6 +102,7 @@
     @Test
     public void bindingToService() {
         SharedConnectivityManager.create(mContext);
+
         verify(mContext).bindService(any(), any(), anyInt());
     }
 
@@ -104,7 +112,8 @@
     @Test
     public void resourcesNotDefined() {
         when(mResources.getString(anyInt())).thenThrow(new Resources.NotFoundException());
-        assertNull(SharedConnectivityManager.create(mContext));
+
+        assertThat(SharedConnectivityManager.create(mContext)).isNull();
     }
 
     /**
@@ -115,8 +124,10 @@
             throws Exception {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
+
         manager.registerCallback(mExecutor, mClientCallback);
         manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
+
         // Since the binder is embedded in a proxy class, the call to registerCallback is done on
         // the proxy. So instead verifying that the proxy is calling the binder.
         verify(mIBinder).transact(anyInt(), any(Parcel.class), any(Parcel.class), anyInt());
@@ -126,9 +137,11 @@
     public void registerCallback_serviceNotConnected_canUnregisterAndReregister() {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
+
         manager.registerCallback(mExecutor, mClientCallback);
         manager.unregisterCallback(mClientCallback);
         manager.registerCallback(mExecutor, mClientCallback);
+
         verify(mClientCallback, never()).onRegisterCallbackFailed(any(Exception.class));
     }
 
@@ -136,7 +149,9 @@
     public void registerCallback_serviceConnected() throws Exception {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
+
         manager.registerCallback(mExecutor, mClientCallback);
+
         verify(mService).registerCallback(any());
         verify(mClientCallback, never()).onRegisterCallbackFailed(any(Exception.class));
     }
@@ -145,8 +160,10 @@
     public void registerCallback_doubleRegistration_shouldFail() throws Exception {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
+
         manager.registerCallback(mExecutor, mClientCallback);
         manager.registerCallback(mExecutor, mClientCallback);
+
         verify(mClientCallback).onRegisterCallbackFailed(any(IllegalStateException.class));
     }
 
@@ -155,7 +172,9 @@
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
         doThrow(new RemoteException()).when(mService).registerCallback(any());
+
         manager.registerCallback(mExecutor, mClientCallback);
+
         verify(mClientCallback).onRegisterCallbackFailed(any(RemoteException.class));
     }
 
@@ -166,22 +185,26 @@
     public void unregisterCallback_withoutRegisteringFirst_serviceNotConnected_shouldFail() {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
-        assertFalse(manager.unregisterCallback(mClientCallback));
+
+        assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
     }
 
     @Test
     public void unregisterCallback_withoutRegisteringFirst_serviceConnected_shouldFail() {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        assertFalse(manager.unregisterCallback(mClientCallback));
+
+        assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
     }
 
     @Test
     public void unregisterCallback() throws Exception {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
+
         manager.registerCallback(mExecutor, mClientCallback);
-        assertTrue(manager.unregisterCallback(mClientCallback));
+
+        assertThat(manager.unregisterCallback(mClientCallback)).isTrue();
         verify(mService).unregisterCallback(any());
     }
 
@@ -189,26 +212,32 @@
     public void unregisterCallback_doubleUnregistration_serviceConnected_shouldFail() {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
+
         manager.registerCallback(mExecutor, mClientCallback);
         manager.unregisterCallback(mClientCallback);
-        assertFalse(manager.unregisterCallback(mClientCallback));
+
+        assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
     }
 
     @Test
     public void unregisterCallback_doubleUnregistration_serviceNotConnected_shouldFail() {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
+
         manager.registerCallback(mExecutor, mClientCallback);
         manager.unregisterCallback(mClientCallback);
-        assertFalse(manager.unregisterCallback(mClientCallback));
+
+        assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
     }
 
     @Test
     public void unregisterCallback_remoteException_shouldFail() throws Exception {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
+
         doThrow(new RemoteException()).when(mService).unregisterCallback(any());
-        assertFalse(manager.unregisterCallback(mClientCallback));
+
+        assertThat(manager.unregisterCallback(mClientCallback)).isFalse();
     }
 
     /**
@@ -217,16 +246,20 @@
     @Test
     public void onServiceConnected_registerCallbackBeforeConnection() {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+
         manager.registerCallback(mExecutor, mClientCallback);
         manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
+
         verify(mClientCallback).onServiceConnected();
     }
 
     @Test
     public void onServiceConnected_registerCallbackAfterConnection() {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+
         manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
         manager.registerCallback(mExecutor, mClientCallback);
+
         verify(mClientCallback).onServiceConnected();
     }
 
@@ -236,77 +269,89 @@
     @Test
     public void onServiceDisconnected_registerCallbackBeforeConnection() {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+
         manager.registerCallback(mExecutor, mClientCallback);
         manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
         manager.getServiceConnection().onServiceDisconnected(COMPONENT_NAME);
+
         verify(mClientCallback).onServiceDisconnected();
     }
 
     @Test
     public void onServiceDisconnected_registerCallbackAfterConnection() {
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+
         manager.getServiceConnection().onServiceConnected(COMPONENT_NAME, mIBinder);
         manager.registerCallback(mExecutor, mClientCallback);
         manager.getServiceConnection().onServiceDisconnected(COMPONENT_NAME);
+
         verify(mClientCallback).onServiceDisconnected();
     }
 
     /**
-     * Verifies connectTetherNetwork behavior.
+     * Verifies connectHotspotNetwork behavior.
      */
     @Test
-    public void connectTetherNetwork_serviceNotConnected_shouldFail() {
-        TetherNetwork network = buildTetherNetwork();
+    public void connectHotspotNetwork_serviceNotConnected_shouldFail() {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
-        assertFalse(manager.connectTetherNetwork(network));
+
+        assertThat(manager.connectHotspotNetwork(network)).isFalse();
     }
 
     @Test
-    public void connectTetherNetwork() throws RemoteException {
-        TetherNetwork network = buildTetherNetwork();
+    public void connectHotspotNetwork() throws RemoteException {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        manager.connectTetherNetwork(network);
-        verify(mService).connectTetherNetwork(network);
+
+        manager.connectHotspotNetwork(network);
+
+        verify(mService).connectHotspotNetwork(network);
     }
 
     @Test
-    public void connectTetherNetwork_remoteException_shouldFail() throws RemoteException {
-        TetherNetwork network = buildTetherNetwork();
+    public void connectHotspotNetwork_remoteException_shouldFail() throws RemoteException {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        doThrow(new RemoteException()).when(mService).connectTetherNetwork(network);
-        assertFalse(manager.connectTetherNetwork(network));
+        doThrow(new RemoteException()).when(mService).connectHotspotNetwork(network);
+
+        assertThat(manager.connectHotspotNetwork(network)).isFalse();
     }
 
     /**
-     * Verifies disconnectTetherNetwork behavior.
+     * Verifies disconnectHotspotNetwork behavior.
      */
     @Test
-    public void disconnectTetherNetwork_serviceNotConnected_shouldFail() {
-        TetherNetwork network = buildTetherNetwork();
+    public void disconnectHotspotNetwork_serviceNotConnected_shouldFail() {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
-        assertFalse(manager.disconnectTetherNetwork(network));
+
+        assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
     }
 
     @Test
-    public void disconnectTetherNetwork() throws RemoteException {
-        TetherNetwork network = buildTetherNetwork();
+    public void disconnectHotspotNetwork() throws RemoteException {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        manager.disconnectTetherNetwork(network);
-        verify(mService).disconnectTetherNetwork(network);
+
+        manager.disconnectHotspotNetwork(network);
+
+        verify(mService).disconnectHotspotNetwork(network);
     }
 
     @Test
-    public void disconnectTetherNetwork_remoteException_shouldFail() throws RemoteException {
-        TetherNetwork network = buildTetherNetwork();
+    public void disconnectHotspotNetwork_remoteException_shouldFail() throws RemoteException {
+        HotspotNetwork network = buildHotspotNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
-        doThrow(new RemoteException()).when(mService).disconnectTetherNetwork(any());
-        assertFalse(manager.disconnectTetherNetwork(network));
+        doThrow(new RemoteException()).when(mService).disconnectHotspotNetwork(any());
+
+        assertThat(manager.disconnectHotspotNetwork(network)).isFalse();
     }
 
     /**
@@ -317,7 +362,8 @@
         KnownNetwork network = buildKnownNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
-        assertFalse(manager.connectKnownNetwork(network));
+
+        assertThat(manager.connectKnownNetwork(network)).isFalse();
     }
 
     @Test
@@ -325,7 +371,9 @@
         KnownNetwork network = buildKnownNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
+
         manager.connectKnownNetwork(network);
+
         verify(mService).connectKnownNetwork(network);
     }
 
@@ -335,7 +383,8 @@
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
         doThrow(new RemoteException()).when(mService).connectKnownNetwork(network);
-        assertFalse(manager.connectKnownNetwork(network));
+
+        assertThat(manager.connectKnownNetwork(network)).isFalse();
     }
 
     /**
@@ -346,7 +395,8 @@
         KnownNetwork network = buildKnownNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(null);
-        assertFalse(manager.forgetKnownNetwork(network));
+
+        assertThat(manager.forgetKnownNetwork(network)).isFalse();
     }
 
     @Test
@@ -354,7 +404,9 @@
         KnownNetwork network = buildKnownNetwork();
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
+
         manager.forgetKnownNetwork(network);
+
         verify(mService).forgetKnownNetwork(network);
     }
 
@@ -364,7 +416,158 @@
         SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
         manager.setService(mService);
         doThrow(new RemoteException()).when(mService).forgetKnownNetwork(network);
-        assertFalse(manager.forgetKnownNetwork(network));
+
+        assertThat(manager.forgetKnownNetwork(network)).isFalse();
+    }
+
+    /**
+     * Verify getters.
+     */
+    @Test
+    public void getHotspotNetworks_serviceNotConnected_shouldReturnEmptyList() {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        manager.setService(null);
+
+        assertThat(manager.getKnownNetworks()).isEmpty();
+    }
+
+    @Test
+    public void getHotspotNetworks_remoteException_shouldReturnEmptyList() throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        manager.setService(mService);
+        doThrow(new RemoteException()).when(mService).getHotspotNetworks();
+
+        assertThat(manager.getKnownNetworks()).isEmpty();
+    }
+
+    @Test
+    public void getHotspotNetworks_shouldReturnNetworksList() throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        List<HotspotNetwork> networks = List.of(buildHotspotNetwork());
+        manager.setService(mService);
+        when(mService.getHotspotNetworks()).thenReturn(networks);
+
+        assertThat(manager.getHotspotNetworks()).containsExactly(buildHotspotNetwork());
+    }
+
+    @Test
+    public void getKnownNetworks_serviceNotConnected_shouldReturnEmptyList()
+            throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        manager.setService(null);
+
+        assertThat(manager.getKnownNetworks()).isEmpty();
+    }
+
+    @Test
+    public void getKnownNetworks_remoteException_shouldReturnEmptyList() throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        manager.setService(mService);
+        doThrow(new RemoteException()).when(mService).getKnownNetworks();
+
+        assertThat(manager.getKnownNetworks()).isEmpty();
+    }
+
+    @Test
+    public void getKnownNetworks_shouldReturnNetworksList() throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        List<KnownNetwork> networks = List.of(buildKnownNetwork());
+        manager.setService(mService);
+        when(mService.getKnownNetworks()).thenReturn(networks);
+
+        assertThat(manager.getKnownNetworks()).containsExactly(buildKnownNetwork());
+    }
+
+    @Test
+    public void getSettingsState_serviceNotConnected_shouldReturnNull() throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        manager.setService(null);
+
+        assertThat(manager.getSettingsState()).isNull();
+    }
+
+    @Test
+    public void getSettingsState_remoteException_shouldReturnNull() throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        manager.setService(mService);
+        doThrow(new RemoteException()).when(mService).getSettingsState();
+
+        assertThat(manager.getSettingsState()).isNull();
+    }
+
+    @Test
+    public void getSettingsState_serviceConnected_shouldReturnState() throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        SharedConnectivitySettingsState state = new SharedConnectivitySettingsState.Builder()
+                .setInstantTetherEnabled(true).setExtras(new Bundle()).build();
+        manager.setService(mService);
+        when(mService.getSettingsState()).thenReturn(state);
+
+        assertThat(manager.getSettingsState()).isEqualTo(state);
+    }
+
+    @Test
+    public void getHotspotNetworkConnectionStatus_serviceNotConnected_shouldReturnNull()
+            throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        manager.setService(null);
+
+        assertThat(manager.getHotspotNetworkConnectionStatus()).isNull();
+    }
+
+    @Test
+    public void getHotspotNetworkConnectionStatus_remoteException_shouldReturnNull()
+            throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        manager.setService(mService);
+        doThrow(new RemoteException()).when(mService).getHotspotNetworkConnectionStatus();
+
+        assertThat(manager.getHotspotNetworkConnectionStatus()).isNull();
+    }
+
+    @Test
+    public void getHotspotNetworkConnectionStatus_serviceConnected_shouldReturnStatus()
+            throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        HotspotNetworkConnectionStatus status = new HotspotNetworkConnectionStatus.Builder()
+                .setStatus(HotspotNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT)
+                .setExtras(new Bundle()).build();
+        manager.setService(mService);
+        when(mService.getHotspotNetworkConnectionStatus()).thenReturn(status);
+
+        assertThat(manager.getHotspotNetworkConnectionStatus()).isEqualTo(status);
+    }
+
+    @Test
+    public void getKnownNetworkConnectionStatus_serviceNotConnected_shouldReturnNull()
+            throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        manager.setService(null);
+
+        assertThat(manager.getKnownNetworkConnectionStatus()).isNull();
+    }
+
+    @Test
+    public void getKnownNetworkConnectionStatus_remoteException_shouldReturnNull()
+            throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        manager.setService(mService);
+        doThrow(new RemoteException()).when(mService).getKnownNetworkConnectionStatus();
+
+        assertThat(manager.getKnownNetworkConnectionStatus()).isNull();
+    }
+
+    @Test
+    public void getKnownNetworkConnectionStatus_serviceConnected_shouldReturnStatus()
+            throws RemoteException {
+        SharedConnectivityManager manager = SharedConnectivityManager.create(mContext);
+        KnownNetworkConnectionStatus status = new KnownNetworkConnectionStatus.Builder()
+                .setStatus(KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED)
+                .setExtras(new Bundle()).build();
+        manager.setService(mService);
+        when(mService.getKnownNetworkConnectionStatus()).thenReturn(status);
+
+        assertThat(manager.getKnownNetworkConnectionStatus()).isEqualTo(status);
     }
 
     private void setResources(@Mock Context context) {
@@ -373,19 +576,21 @@
                 .thenReturn(SERVICE_PACKAGE_NAME, SERVICE_INTENT_ACTION);
     }
 
-    private TetherNetwork buildTetherNetwork() {
-        return new TetherNetwork.Builder()
+    private HotspotNetwork buildHotspotNetwork() {
+        HotspotNetwork.Builder builder = new HotspotNetwork.Builder()
                 .setDeviceId(DEVICE_ID)
-                .setDeviceInfo(DEVICE_INFO)
-                .setNetworkType(NETWORK_TYPE)
+                .setNetworkProviderInfo(NETWORK_PROVIDER_INFO)
+                .setHostNetworkType(NETWORK_TYPE)
                 .setNetworkName(NETWORK_NAME)
-                .setHotspotSsid(HOTSPOT_SSID)
-                .setHotspotSecurityTypes(HOTSPOT_SECURITY_TYPES)
-                .build();
+                .setHotspotSsid(HOTSPOT_SSID);
+        Arrays.stream(HOTSPOT_SECURITY_TYPES).forEach(builder::addHotspotSecurityType);
+        return builder.build();
     }
 
     private KnownNetwork buildKnownNetwork() {
-        return new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE).setSsid(SSID)
-                .setSecurityTypes(SECURITY_TYPES).build();
+        KnownNetwork.Builder builder = new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE)
+                .setSsid(SSID).setNetworkProviderInfo(NETWORK_PROVIDER_INFO);
+        Arrays.stream(SECURITY_TYPES).forEach(builder::addSecurityType);
+        return builder.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
index 3137c72..752b749 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/SharedConnectivitySettingsStateTest.java
@@ -16,8 +16,7 @@
 
 package android.net.wifi.sharedconnectivity.app;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
+import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Parcel;
 
@@ -26,7 +25,7 @@
 import org.junit.Test;
 
 /**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState}.
+ * Unit tests for {@link SharedConnectivitySettingsState}.
  */
 @SmallTest
 public class SharedConnectivitySettingsStateTest {
@@ -51,8 +50,8 @@
         SharedConnectivitySettingsState fromParcel =
                 SharedConnectivitySettingsState.CREATOR.createFromParcel(parcelR);
 
-        assertEquals(state, fromParcel);
-        assertEquals(state.hashCode(), fromParcel.hashCode());
+        assertThat(fromParcel).isEqualTo(state);
+        assertThat(fromParcel.hashCode()).isEqualTo(state.hashCode());
     }
 
     /**
@@ -62,11 +61,11 @@
     public void testEqualsOperation() {
         SharedConnectivitySettingsState state1 = buildSettingsStateBuilder().build();
         SharedConnectivitySettingsState state2 = buildSettingsStateBuilder().build();
-        assertEquals(state1, state2);
+        assertThat(state1).isEqualTo(state2);
 
         SharedConnectivitySettingsState.Builder builder = buildSettingsStateBuilder()
                 .setInstantTetherEnabled(INSTANT_TETHER_STATE_1);
-        assertNotEquals(state1, builder.build());
+        assertThat(builder.build()).isNotEqualTo(state1);
     }
 
     /**
@@ -75,7 +74,15 @@
     @Test
     public void testGetMethods() {
         SharedConnectivitySettingsState state = buildSettingsStateBuilder().build();
-        assertEquals(state.isInstantTetherEnabled(), INSTANT_TETHER_STATE);
+        assertThat(state.isInstantTetherEnabled()).isEqualTo(INSTANT_TETHER_STATE);
+    }
+
+    @Test
+    public void testHashCode() {
+        SharedConnectivitySettingsState state1 = buildSettingsStateBuilder().build();
+        SharedConnectivitySettingsState state2 = buildSettingsStateBuilder().build();
+
+        assertThat(state1.hashCode()).isEqualTo(state2.hashCode());
     }
 
     private SharedConnectivitySettingsState.Builder buildSettingsStateBuilder() {
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java
deleted file mode 100644
index 1d9c2e6..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkConnectionStatusTest.java
+++ /dev/null
@@ -1,128 +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 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.TetherNetwork.NETWORK_TYPE_CELLULAR;
-import static android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.CONNECTION_STATUS_ENABLING_HOTSPOT;
-import static android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus.CONNECTION_STATUS_TETHERING_TIMEOUT;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-
-import android.os.Bundle;
-import android.os.Parcel;
-
-import androidx.test.filters.SmallTest;
-
-import org.junit.Test;
-
-/**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.app.TetherNetworkConnectionStatus}.
- */
-@SmallTest
-public class TetherNetworkConnectionStatusTest {
-    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 String BUNDLE_KEY = "INT-KEY";
-
-    /**
-     * Verifies parcel serialization/deserialization.
-     */
-    @Test
-    public void testParcelOperation() {
-        TetherNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
-
-        Parcel parcelW = Parcel.obtain();
-        status.writeToParcel(parcelW, 0);
-        byte[] bytes = parcelW.marshall();
-        parcelW.recycle();
-
-        Parcel parcelR = Parcel.obtain();
-        parcelR.unmarshall(bytes, 0, bytes.length);
-        parcelR.setDataPosition(0);
-        TetherNetworkConnectionStatus fromParcel =
-                TetherNetworkConnectionStatus.CREATOR.createFromParcel(parcelR);
-
-        assertEquals(status, fromParcel);
-        assertEquals(status.hashCode(), fromParcel.hashCode());
-    }
-
-    /**
-     * Verifies the Equals operation
-     */
-    @Test
-    public void testEqualsOperation() {
-        TetherNetworkConnectionStatus status1 = buildConnectionStatusBuilder().build();
-        TetherNetworkConnectionStatus status2 = buildConnectionStatusBuilder().build();
-        assertEquals(status2, status2);
-
-        TetherNetworkConnectionStatus.Builder builder = buildConnectionStatusBuilder()
-                .setStatus(CONNECTION_STATUS_TETHERING_TIMEOUT);
-        assertNotEquals(status1, builder.build());
-
-        builder = buildConnectionStatusBuilder()
-                .setTetherNetwork(buildTetherNetworkBuilder().setDeviceId(DEVICE_ID_1).build());
-        assertNotEquals(status1, builder.build());
-    }
-
-    /**
-     * Verifies the get methods return the expected data.
-     */
-    @Test
-    public void testGetMethods() {
-        TetherNetworkConnectionStatus status = buildConnectionStatusBuilder().build();
-        assertEquals(status.getStatus(), CONNECTION_STATUS_ENABLING_HOTSPOT);
-        assertEquals(status.getTetherNetwork(), buildTetherNetworkBuilder().build());
-        assertEquals(status.getExtras().getInt(BUNDLE_KEY), buildBundle().getInt(BUNDLE_KEY));
-    }
-
-    private TetherNetworkConnectionStatus.Builder buildConnectionStatusBuilder() {
-
-        return new TetherNetworkConnectionStatus.Builder()
-                .setStatus(CONNECTION_STATUS_ENABLING_HOTSPOT)
-                .setTetherNetwork(buildTetherNetworkBuilder().build())
-                .setExtras(buildBundle());
-    }
-
-    private Bundle buildBundle() {
-        Bundle bundle = new Bundle();
-        bundle.putInt(BUNDLE_KEY, 1);
-        return bundle;
-    }
-
-    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/app/TetherNetworkTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java
deleted file mode 100644
index b01aec4..0000000
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/app/TetherNetworkTest.java
+++ /dev/null
@@ -1,139 +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 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
index d7f7fea..cf437b7 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
@@ -16,14 +16,29 @@
 
 package android.net.wifi.sharedconnectivity.service;
 
-import static org.junit.Assert.assertNotNull;
+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.HotspotNetwork.NETWORK_TYPE_CELLULAR;
+import static android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.CONNECTION_STATUS_UNKNOWN;
+import static android.net.wifi.sharedconnectivity.app.KnownNetwork.NETWORK_SOURCE_NEARBY_SELF;
+import static android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.CONNECTION_STATUS_SAVED;
+import static android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.DEVICE_TYPE_TABLET;
+
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
 import android.content.Intent;
+import android.net.wifi.sharedconnectivity.app.HotspotNetwork;
+import android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus;
 import android.net.wifi.sharedconnectivity.app.KnownNetwork;
-import android.net.wifi.sharedconnectivity.app.TetherNetwork;
+import android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus;
+import android.net.wifi.sharedconnectivity.app.NetworkProviderInfo;
+import android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState;
+import android.os.Bundle;
 import android.os.Looper;
+import android.os.RemoteException;
 
 import androidx.annotation.NonNull;
 import androidx.test.filters.SmallTest;
@@ -33,11 +48,41 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.List;
+
 /**
- * Unit tests for {@link android.net.wifi.sharedconnectivity.service.SharedConnectivityService}.
+ * Unit tests for {@link SharedConnectivityService}.
  */
 @SmallTest
 public class SharedConnectivityServiceTest {
+    private static final NetworkProviderInfo NETWORK_PROVIDER_INFO =
+            new NetworkProviderInfo.Builder()
+                    .setDeviceType(DEVICE_TYPE_TABLET).setDeviceName("TEST_NAME").setModelName(
+                            "TEST_MODEL")
+                    .setConnectionStrength(2).setBatteryPercentage(50).build();
+    private static final HotspotNetwork HOTSPOT_NETWORK =
+            new HotspotNetwork.Builder().setDeviceId(1).setNetworkProviderInfo(
+                            NETWORK_PROVIDER_INFO)
+                    .setHostNetworkType(NETWORK_TYPE_CELLULAR).setNetworkName("TEST_NETWORK")
+                    .setHotspotSsid("TEST_SSID").setHotspotBssid("TEST_BSSID")
+                    .addHotspotSecurityType(SECURITY_TYPE_WEP)
+                    .addHotspotSecurityType(SECURITY_TYPE_EAP).build();
+    private static final List<HotspotNetwork> HOTSPOT_NETWORKS = List.of(HOTSPOT_NETWORK);
+    private static final KnownNetwork KNOWN_NETWORK =
+            new KnownNetwork.Builder().setNetworkSource(NETWORK_SOURCE_NEARBY_SELF)
+                    .setSsid("TEST_SSID").addSecurityType(SECURITY_TYPE_WEP)
+                    .addSecurityType(SECURITY_TYPE_EAP).setNetworkProviderInfo(
+                            NETWORK_PROVIDER_INFO).build();
+    private static final List<KnownNetwork> KNOWN_NETWORKS = List.of(KNOWN_NETWORK);
+    private static final SharedConnectivitySettingsState SETTINGS_STATE =
+            new SharedConnectivitySettingsState.Builder().setInstantTetherEnabled(true)
+                    .setExtras(Bundle.EMPTY).build();
+    private static final HotspotNetworkConnectionStatus TETHER_NETWORK_CONNECTION_STATUS =
+            new HotspotNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_UNKNOWN)
+                    .setHotspotNetwork(HOTSPOT_NETWORK).setExtras(Bundle.EMPTY).build();
+    private static final KnownNetworkConnectionStatus KNOWN_NETWORK_CONNECTION_STATUS =
+            new KnownNetworkConnectionStatus.Builder().setStatus(CONNECTION_STATUS_SAVED)
+                    .setKnownNetwork(KNOWN_NETWORK).setExtras(Bundle.EMPTY).build();
 
     @Mock
     Context mContext;
@@ -48,16 +93,20 @@
         }
 
         @Override
-        public void onConnectTetherNetwork(@NonNull TetherNetwork network) {}
+        public void onConnectHotspotNetwork(@NonNull HotspotNetwork network) {
+        }
 
         @Override
-        public void onDisconnectTetherNetwork(@NonNull TetherNetwork network) {}
+        public void onDisconnectHotspotNetwork(@NonNull HotspotNetwork network) {
+        }
 
         @Override
-        public void onConnectKnownNetwork(@NonNull KnownNetwork network) {}
+        public void onConnectKnownNetwork(@NonNull KnownNetwork network) {
+        }
 
         @Override
-        public void onForgetKnownNetwork(@NonNull KnownNetwork network) {}
+        public void onForgetKnownNetwork(@NonNull KnownNetwork network) {
+        }
     }
 
     @Before
@@ -66,20 +115,70 @@
         when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
     }
 
-    /**
-     * Verifies service returns
-     */
     @Test
-    public void testOnBind() {
+    public void onBind_isNotNull() {
         SharedConnectivityService service = createService();
-        assertNotNull(service.onBind(new Intent()));
+
+        assertThat(service.onBind(new Intent())).isNotNull();
     }
 
     @Test
-    public void testCallbacks() {
+    public void getHotspotNetworks() throws RemoteException {
         SharedConnectivityService service = createService();
         ISharedConnectivityService.Stub binder =
                 (ISharedConnectivityService.Stub) service.onBind(new Intent());
+
+        service.setHotspotNetworks(HOTSPOT_NETWORKS);
+
+        assertThat(binder.getHotspotNetworks())
+                .containsExactlyElementsIn(List.copyOf(HOTSPOT_NETWORKS));
+    }
+
+    @Test
+    public void getKnownNetworks() throws RemoteException {
+        SharedConnectivityService service = createService();
+        ISharedConnectivityService.Stub binder =
+                (ISharedConnectivityService.Stub) service.onBind(new Intent());
+
+        service.setKnownNetworks(KNOWN_NETWORKS);
+
+        assertThat(binder.getKnownNetworks())
+                .containsExactlyElementsIn(List.copyOf(KNOWN_NETWORKS));
+    }
+
+    @Test
+    public void getSharedConnectivitySettingsState() throws RemoteException {
+        SharedConnectivityService service = createService();
+        ISharedConnectivityService.Stub binder =
+                (ISharedConnectivityService.Stub) service.onBind(new Intent());
+
+        service.setSettingsState(SETTINGS_STATE);
+
+        assertThat(binder.getSettingsState()).isEqualTo(SETTINGS_STATE);
+    }
+
+    @Test
+    public void updateHotspotNetworkConnectionStatus() throws RemoteException {
+        SharedConnectivityService service = createService();
+        ISharedConnectivityService.Stub binder =
+                (ISharedConnectivityService.Stub) service.onBind(new Intent());
+
+        service.updateHotspotNetworkConnectionStatus(TETHER_NETWORK_CONNECTION_STATUS);
+
+        assertThat(binder.getHotspotNetworkConnectionStatus())
+                .isEqualTo(TETHER_NETWORK_CONNECTION_STATUS);
+    }
+
+    @Test
+    public void updateKnownNetworkConnectionStatus() throws RemoteException {
+        SharedConnectivityService service = createService();
+        ISharedConnectivityService.Stub binder =
+                (ISharedConnectivityService.Stub) service.onBind(new Intent());
+
+        service.updateKnownNetworkConnectionStatus(KNOWN_NETWORK_CONNECTION_STATUS);
+
+        assertThat(binder.getKnownNetworkConnectionStatus())
+                .isEqualTo(KNOWN_NETWORK_CONNECTION_STATUS);
     }
 
     private SharedConnectivityService createService() {