Merge "[bc25] Create ACONFIG flag for the BC25 Dual Shade feature." into main
diff --git a/Ravenwood.bp b/Ravenwood.bp
index 7c7c0e2..74382a6 100644
--- a/Ravenwood.bp
+++ b/Ravenwood.bp
@@ -34,6 +34,7 @@
 
         "--debug-log $(location hoststubgen_framework-minus-apex.log) " +
         "--stats-file $(location hoststubgen_framework-minus-apex_stats.csv) " +
+        "--supported-api-list-file $(location hoststubgen_framework-minus-apex_apis.csv) " +
 
         "--out-impl-jar $(location ravenwood.jar) " +
 
@@ -58,6 +59,7 @@
 
         "hoststubgen_framework-minus-apex.log",
         "hoststubgen_framework-minus-apex_stats.csv",
+        "hoststubgen_framework-minus-apex_apis.csv",
     ],
     visibility: ["//visibility:private"],
 }
@@ -90,6 +92,18 @@
     ],
 }
 
+genrule {
+    name: "framework-minus-apex.ravenwood.apis",
+    defaults: ["ravenwood-internal-only-visibility-genrule"],
+    cmd: "cp $(in) $(out)",
+    srcs: [
+        ":framework-minus-apex.ravenwood-base{hoststubgen_framework-minus-apex_apis.csv}",
+    ],
+    out: [
+        "hoststubgen_framework-minus-apex_apis.csv",
+    ],
+}
+
 java_library {
     name: "services.core-for-hoststubgen",
     installable: false, // host only jar.
@@ -108,6 +122,7 @@
 
         "--debug-log $(location hoststubgen_services.core.log) " +
         "--stats-file $(location hoststubgen_services.core_stats.csv) " +
+        "--supported-api-list-file $(location hoststubgen_services.core_apis.csv) " +
 
         "--out-impl-jar $(location ravenwood.jar) " +
 
@@ -132,6 +147,7 @@
 
         "hoststubgen_services.core.log",
         "hoststubgen_services.core_stats.csv",
+        "hoststubgen_services.core_apis.csv",
     ],
     visibility: ["//visibility:private"],
 }
@@ -161,6 +177,18 @@
     ],
 }
 
+genrule {
+    name: "services.core.ravenwood.apis",
+    defaults: ["ravenwood-internal-only-visibility-genrule"],
+    cmd: "cp $(in) $(out)",
+    srcs: [
+        ":services.core.ravenwood-base{hoststubgen_services.core_apis.csv}",
+    ],
+    out: [
+        "hoststubgen_services.core_apis.csv",
+    ],
+}
+
 java_library {
     name: "services.core.ravenwood-jarjar",
     installable: false,
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
index be4b720..d52c4ce 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
@@ -36,10 +36,9 @@
 import com.android.server.job.JobSchedulerService;
 import com.android.server.job.StateControllerProto;
 
+import java.util.Comparator;
 import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
+import java.util.PriorityQueue;
 import java.util.function.Predicate;
 
 /**
@@ -64,8 +63,17 @@
     private volatile long mLastFiredDelayExpiredElapsedMillis;
 
     private AlarmManager mAlarmService = null;
-    /** List of tracked jobs, sorted asc. by deadline */
-    private final List<JobStatus> mTrackedJobs = new LinkedList<>();
+
+    /** List of tracked jobs, ordered by deadline (lowest i.e. earliest first) */
+    private final PriorityQueue<JobStatus> mTrackedJobs =
+            new PriorityQueue<>(
+                    new Comparator<JobStatus>() {
+                        public int compare(JobStatus left, JobStatus right) {
+                            return Long.compare(
+                                    left.getLatestRunTimeElapsed(),
+                                    right.getLatestRunTimeElapsed());
+                        }
+                    });
 
     public TimeController(JobSchedulerService service) {
         super(service);
@@ -102,20 +110,7 @@
                 }
             }
 
-            boolean isInsert = false;
-            ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size());
-            while (it.hasPrevious()) {
-                JobStatus ts = it.previous();
-                if (ts.getLatestRunTimeElapsed() < job.getLatestRunTimeElapsed()) {
-                    // Insert
-                    isInsert = true;
-                    break;
-                }
-            }
-            if (isInsert) {
-                it.next();
-            }
-            it.add(job);
+            mTrackedJobs.add(job);
 
             job.setTrackingController(JobStatus.TRACKING_TIME);
             WorkSource ws =
@@ -226,7 +221,7 @@
             String nextExpiryPackageName = null;
             final long nowElapsedMillis = sElapsedRealtimeClock.millis();
 
-            ListIterator<JobStatus> it = mTrackedJobs.listIterator();
+            Iterator<JobStatus> it = mTrackedJobs.iterator();
             while (it.hasNext()) {
                 JobStatus job = it.next();
                 if (!job.hasDeadlineConstraint()) {
diff --git a/config/Android.bp b/config/Android.bp
index dd681ca..adce203 100644
--- a/config/Android.bp
+++ b/config/Android.bp
@@ -29,6 +29,13 @@
     ],
 }
 
+prebuilt_etc {
+    name: "preloaded-classes",
+    src: "preloaded-classes",
+    filename: "preloaded-classes",
+    installable: false,
+}
+
 filegroup {
     name: "preloaded-classes-denylist",
     srcs: ["preloaded-classes-denylist"],
diff --git a/core/api/current.txt b/core/api/current.txt
index 7d9ce58..2f2a765 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -32743,7 +32743,7 @@
     field public static final int S_V2 = 32; // 0x20
     field public static final int TIRAMISU = 33; // 0x21
     field public static final int UPSIDE_DOWN_CAKE = 34; // 0x22
-    field public static final int VANILLA_ICE_CREAM = 10000; // 0x2710
+    field public static final int VANILLA_ICE_CREAM = 35; // 0x23
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 628611d..0372b7b 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -596,6 +596,7 @@
     method @Deprecated public int getDeviceOwnerType(@NonNull android.content.ComponentName);
     method @Nullable public String getDevicePolicyManagementRoleHolderUpdaterPackage();
     method @NonNull public java.util.Set<java.lang.String> getDisallowedSystemApps(@NonNull android.content.ComponentName, int, @NonNull String);
+    method @FlaggedApi("android.app.admin.flags.headless_device_owner_provisioning_fix_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public int getHeadlessDeviceOwnerMode();
     method public long getLastBugReportRequestTime();
     method public long getLastNetworkLogRetrievalTime();
     method public long getLastSecurityLogRetrievalTime();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index dd6bc55..b9906bf 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -84,6 +84,7 @@
 import android.content.res.ApkAssets;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -118,9 +119,11 @@
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.util.AttributeSet;
 import android.util.LauncherIcons;
 import android.util.Log;
 import android.util.Slog;
+import android.util.Xml;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.Immutable;
@@ -132,6 +135,9 @@
 
 import libcore.util.EmptyArray;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -4090,4 +4096,38 @@
             }
         }
     }
+
+    @Override
+    public TypedArray extractPackageItemInfoAttributes(PackageItemInfo info, String name,
+            String rootTag, int[] attributes) {
+        if (info == null || info.metaData == null) {
+            return null;
+        }
+
+        try (XmlResourceParser parser = info.loadXmlMetaData(this, name)) {
+            if (parser == null) {
+                Log.w(TAG, "No " + name + " metadata");
+                return null;
+            }
+
+            final AttributeSet attrs = Xml.asAttributeSet(parser);
+            while (true) {
+                final int type = parser.next();
+                if (type == XmlPullParser.END_DOCUMENT || type == XmlPullParser.START_TAG) {
+                    break;
+                }
+            }
+
+            if (!TextUtils.equals(parser.getName(), rootTag)) {
+                Log.w(TAG, "Metadata does not start with " + name + " tag");
+                return null;
+            }
+
+            return getResourcesForApplication(info.getApplicationInfo())
+                    .obtainAttributes(attrs, attributes);
+        } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) {
+            Log.e(TAG, "Error parsing: " + info.packageName, e);
+            return null;
+        }
+    }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 9058713..69f29f3 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -58,6 +58,7 @@
 import static android.app.admin.flags.Flags.FLAG_DEVICE_THEFT_API_ENABLED;
 import static android.app.admin.flags.Flags.FLAG_ESIM_MANAGEMENT_ENABLED;
 import static android.app.admin.flags.Flags.FLAG_DEVICE_POLICY_SIZE_TRACKING_ENABLED;
+import static android.app.admin.flags.Flags.FLAG_HEADLESS_DEVICE_OWNER_PROVISIONING_FIX_ENABLED;
 import static android.app.admin.flags.Flags.FLAG_HEADLESS_DEVICE_OWNER_SINGLE_USER_ENABLED;
 import static android.app.admin.flags.Flags.FLAG_SECURITY_LOG_V2_ENABLED;
 import static android.app.admin.flags.Flags.onboardingBugreportV2Enabled;
@@ -17724,6 +17725,9 @@
      *
      * @hide
      */
+    @TestApi
+    @FlaggedApi(FLAG_HEADLESS_DEVICE_OWNER_PROVISIONING_FIX_ENABLED)
+    @RequiresPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
     @DeviceAdminInfo.HeadlessDeviceOwnerMode
     public int getHeadlessDeviceOwnerMode() {
         if (!Flags.headlessDeviceOwnerProvisioningFixEnabled()) {
diff --git a/core/java/android/app/admin/EnterprisePlatform_OWNERS b/core/java/android/app/admin/EnterprisePlatform_OWNERS
index 4d1ed590..9da526f 100644
--- a/core/java/android/app/admin/EnterprisePlatform_OWNERS
+++ b/core/java/android/app/admin/EnterprisePlatform_OWNERS
@@ -1,2 +1,3 @@
 sandness@google.com #{LAST_RESORT_SUGGESTION}
-scottjonathan@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
+scottjonathan@google.com #{LAST_RESORT_SUGGESTION}
+rubinxu@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index a08d659..8fe5ae0 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -382,6 +382,10 @@
     @GuardedBy("mListeners")
     private final ArrayList<OnAssociationsChangedListenerProxy> mListeners = new ArrayList<>();
 
+    @GuardedBy("mTransportsChangedListeners")
+    private final ArrayList<OnTransportsChangedListenerProxy> mTransportsChangedListeners =
+            new ArrayList<>();
+
     @GuardedBy("mTransports")
     private final SparseArray<Transport> mTransports = new SparseArray<>();
 
@@ -998,12 +1002,15 @@
             return;
         }
 
-        final OnTransportsChangedListenerProxy proxy = new OnTransportsChangedListenerProxy(
-                executor, listener);
-        try {
-            mService.addOnTransportsChangedListener(proxy);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+        synchronized (mTransportsChangedListeners) {
+            final OnTransportsChangedListenerProxy proxy = new OnTransportsChangedListenerProxy(
+                    executor, listener);
+            try {
+                mService.addOnTransportsChangedListener(proxy);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+            mTransportsChangedListeners.add(proxy);
         }
     }
 
@@ -1022,12 +1029,20 @@
             return;
         }
 
-        final OnTransportsChangedListenerProxy proxy = new OnTransportsChangedListenerProxy(
-                null, listener);
-        try {
-            mService.removeOnTransportsChangedListener(proxy);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+        synchronized (mTransportsChangedListeners) {
+            final Iterator<OnTransportsChangedListenerProxy> iterator =
+                    mTransportsChangedListeners.iterator();
+            while (iterator.hasNext()) {
+                final OnTransportsChangedListenerProxy proxy = iterator.next();
+                if (proxy.mListener == listener) {
+                    try {
+                        mService.removeOnTransportsChangedListener(proxy);
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
+                    }
+                    iterator.remove();
+                }
+            }
         }
     }
 
@@ -1884,7 +1899,7 @@
             mLocalOut = new ParcelFileDescriptor.AutoCloseOutputStream(localFd);
 
             try {
-                mService.attachSystemDataTransport(mContext.getPackageName(),
+                mService.attachSystemDataTransport(mContext.getOpPackageName(),
                         mContext.getUserId(), mAssociationId, remoteFd);
             } catch (RemoteException e) {
                 throw new IOException("Failed to configure transport", e);
@@ -1921,9 +1936,9 @@
             mStopped = true;
 
             try {
-                mService.detachSystemDataTransport(mContext.getPackageName(),
+                mService.detachSystemDataTransport(mContext.getOpPackageName(),
                         mContext.getUserId(), mAssociationId);
-            } catch (RemoteException e) {
+            } catch (RemoteException | IllegalArgumentException e) {
                 Log.w(TAG, "Failed to detach transport", e);
             }
 
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index cae4fab..495ae60 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -2700,7 +2700,7 @@
     /**
      * @hide
      */
-    @Override protected ApplicationInfo getApplicationInfo() {
+    @Override public ApplicationInfo getApplicationInfo() {
         return this;
     }
 
diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java
index ff48ffa..4d9ecc4 100644
--- a/core/java/android/content/pm/ComponentInfo.java
+++ b/core/java/android/content/pm/ComponentInfo.java
@@ -284,7 +284,7 @@
     /**
      * @hide
      */
-    @Override protected ApplicationInfo getApplicationInfo() {
+    @Override public ApplicationInfo getApplicationInfo() {
         return applicationInfo;
     }
 }
diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java
index 1f821b9..51285de 100644
--- a/core/java/android/content/pm/PackageItemInfo.java
+++ b/core/java/android/content/pm/PackageItemInfo.java
@@ -511,7 +511,7 @@
      *
      * @hide
      */
-    protected ApplicationInfo getApplicationInfo() {
+    public ApplicationInfo getApplicationInfo() {
         return null;
     }
 
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f5bff9d..83285e0 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -62,6 +62,7 @@
 import android.content.pm.verify.domain.DomainVerificationManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Rect;
 import android.graphics.drawable.AdaptiveIconDrawable;
@@ -11743,4 +11744,17 @@
         throw new UnsupportedOperationException(
                 "parseAndroidManifest not implemented in subclass");
     }
+
+    /**
+     * @param info    The {@link ServiceInfo} to pull the attributes from.
+     * @param name    The name of the Xml metadata where the attributes are stored.
+     * @param rootTag The root tag of the attributes.
+     * @return A {@link TypedArray} of attributes if successful, {@code null} otherwise.
+     * @hide
+     */
+    public TypedArray extractPackageItemInfoAttributes(PackageItemInfo info, String name,
+            String rootTag, int[] attributes) {
+        throw new UnsupportedOperationException(
+                "parseServiceMetadata not implemented in subclass");
+    }
 }
diff --git a/core/java/android/hardware/biometrics/BiometricFaceConstants.java b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
index 2ba1d89..ac47c8d 100644
--- a/core/java/android/hardware/biometrics/BiometricFaceConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFaceConstants.java
@@ -34,7 +34,7 @@
  *
  * @hide
  */
-public interface BiometricFaceConstants {
+public class BiometricFaceConstants {
     //
     // Accessibility constants
     //
@@ -43,12 +43,12 @@
      * authentication. Note this is to accommodate people who have limited
      * vision.
      */
-    int FEATURE_REQUIRE_ATTENTION = 1;
+    public static final int FEATURE_REQUIRE_ATTENTION = 1;
     /**
      * Require a diverse set of poses during enrollment. Note this is to
      * accommodate people with limited mobility.
      */
-    int FEATURE_REQUIRE_REQUIRE_DIVERSITY = 2;
+    public static final int FEATURE_REQUIRE_REQUIRE_DIVERSITY = 2;
 
     //
     // Error messages from face authentication hardware during initialization, enrollment,
@@ -75,49 +75,49 @@
             BIOMETRIC_ERROR_POWER_PRESSED,
     })
     @Retention(RetentionPolicy.SOURCE)
-    @interface FaceError {}
+    public @interface FaceError {}
 
     /**
      * The hardware is unavailable. Try again later.
      */
-    int FACE_ERROR_HW_UNAVAILABLE = 1;
+    public static final int FACE_ERROR_HW_UNAVAILABLE = 1;
 
     /**
      * Error state returned when the sensor was unable to process the current image.
      */
-    int FACE_ERROR_UNABLE_TO_PROCESS = 2;
+    public static final int FACE_ERROR_UNABLE_TO_PROCESS = 2;
 
     /**
      * Error state returned when the current request has been running too long. This is intended to
      * prevent programs from waiting for the face authentication sensor indefinitely. The timeout is
      * platform and sensor-specific, but is generally on the order of 30 seconds.
      */
-    int FACE_ERROR_TIMEOUT = 3;
+    public static final int FACE_ERROR_TIMEOUT = 3;
 
     /**
      * Error state returned for operations like enrollment; the operation cannot be completed
      * because there's not enough storage remaining to complete the operation.
      */
-    int FACE_ERROR_NO_SPACE = 4;
+    public static final int FACE_ERROR_NO_SPACE = 4;
 
     /**
      * The operation was canceled because the face authentication sensor is unavailable. For
      * example, this may happen when the user is switched, the device is locked or another pending
      * operation prevents or disables it.
      */
-    int FACE_ERROR_CANCELED = 5;
+    public static final int FACE_ERROR_CANCELED = 5;
 
     /**
      * The {@link FaceManager#remove} call failed. Typically this will happen when the
      * provided face id was incorrect.
      */
-    int FACE_ERROR_UNABLE_TO_REMOVE = 6;
+    public static final int FACE_ERROR_UNABLE_TO_REMOVE = 6;
 
     /**
      * The operation was canceled because the API is locked out due to too many attempts.
      * This occurs after 5 failed attempts, and lasts for 30 seconds.
      */
-    int FACE_ERROR_LOCKOUT = 7;
+    public static final int FACE_ERROR_LOCKOUT = 7;
 
     /**
      * Hardware vendors may extend this list if there are conditions that do not fall under one of
@@ -127,46 +127,46 @@
      * expected to show the error message string if they happen, but are advised not to rely on the
      * message id since they will be device and vendor-specific
      */
-    int FACE_ERROR_VENDOR = 8;
+    public static final int FACE_ERROR_VENDOR = 8;
 
     /**
      * The operation was canceled because FACE_ERROR_LOCKOUT occurred too many times.
      * Face authentication is disabled until the user unlocks with strong authentication
      * (PIN/Pattern/Password)
      */
-    int FACE_ERROR_LOCKOUT_PERMANENT = 9;
+    public static final int FACE_ERROR_LOCKOUT_PERMANENT = 9;
 
     /**
      * The user canceled the operation. Upon receiving this, applications should use alternate
      * authentication (e.g. a password). The application should also provide the means to return
      * to face authentication, such as a "use face authentication" button.
      */
-    int FACE_ERROR_USER_CANCELED = 10;
+    public static final int FACE_ERROR_USER_CANCELED = 10;
 
     /**
      * The user does not have a face enrolled.
      */
-    int FACE_ERROR_NOT_ENROLLED = 11;
+    public static final int FACE_ERROR_NOT_ENROLLED = 11;
 
     /**
      * The device does not have a face sensor. This message will propagate if the calling app
      * ignores the result from PackageManager.hasFeature(FEATURE_FACE) and calls
      * this API anyway. Apps should always check for the feature before calling this API.
      */
-    int FACE_ERROR_HW_NOT_PRESENT = 12;
+    public static final int FACE_ERROR_HW_NOT_PRESENT = 12;
 
     /**
      * The user pressed the negative button. This is a placeholder that is currently only used
      * by the support library.
      */
-    int FACE_ERROR_NEGATIVE_BUTTON = 13;
+    public static final int FACE_ERROR_NEGATIVE_BUTTON = 13;
 
     /**
      * The device does not have pin, pattern, or password set up. See
      * {@link BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)} and
      * {@link KeyguardManager#isDeviceSecure()}
      */
-    int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
+    public static final int BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL = 14;
 
     /**
      * A security vulnerability has been discovered and the sensor is unavailable until a
@@ -174,30 +174,30 @@
      * authentication was requested with {@link Authenticators#BIOMETRIC_STRONG}, but the
      * sensor's strength can currently only meet {@link Authenticators#BIOMETRIC_WEAK}.
      */
-    int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
+    public static final int BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED = 15;
 
     /**
      * Authentication cannot proceed because re-enrollment is required.
      */
-    int BIOMETRIC_ERROR_RE_ENROLL = 16;
+    public static final int BIOMETRIC_ERROR_RE_ENROLL = 16;
 
     /**
      * Unknown error received from the HAL.
      */
-    int FACE_ERROR_UNKNOWN = 17;
+    public static final int FACE_ERROR_UNKNOWN = 17;
 
     /**
      * A power press stopped this biometric operation.
      * @hide
      */
-    int BIOMETRIC_ERROR_POWER_PRESSED = 19;
+    public static final int BIOMETRIC_ERROR_POWER_PRESSED = 19;
 
     /**
      * Vendor codes received from the HAL start at 0. Codes that the framework exposes to keyguard
      * append this value for some reason. We should probably remove this and just send the actual
      * vendor code.
      */
-    int FACE_ERROR_VENDOR_BASE = 1000;
+    public static final int FACE_ERROR_VENDOR_BASE = 1000;
 
     //
     // Image acquisition messages. These will not be sent to the user, since they conflict with
@@ -232,18 +232,18 @@
             FACE_ACQUIRED_DARK_GLASSES_DETECTED,
             FACE_ACQUIRED_MOUTH_COVERING_DETECTED})
     @Retention(RetentionPolicy.SOURCE)
-    @interface FaceAcquired {}
+    public @interface FaceAcquired {}
 
     /**
      * The image acquired was good.
      */
-    int FACE_ACQUIRED_GOOD = 0;
+    public static final int FACE_ACQUIRED_GOOD = 0;
 
     /**
      * The face image was not good enough to process due to a detected condition.
      * (See {@link #FACE_ACQUIRED_TOO_BRIGHT or @link #FACE_ACQUIRED_TOO_DARK}).
      */
-    int FACE_ACQUIRED_INSUFFICIENT = 1;
+    public static final int FACE_ACQUIRED_INSUFFICIENT = 1;
 
     /**
      * The face image was too bright due to too much ambient light.
@@ -252,7 +252,7 @@
      * The user is expected to take action to retry in better lighting conditions
      * when this is returned.
      */
-    int FACE_ACQUIRED_TOO_BRIGHT = 2;
+    public static final int FACE_ACQUIRED_TOO_BRIGHT = 2;
 
     /**
      * The face image was too dark due to illumination light obscured.
@@ -261,65 +261,65 @@
      * The user is expected to take action to retry in better lighting conditions
      * when this is returned.
      */
-    int FACE_ACQUIRED_TOO_DARK = 3;
+    public static final int FACE_ACQUIRED_TOO_DARK = 3;
 
     /**
      * The detected face is too close to the sensor, and the image can't be processed.
      * The user should be informed to move farther from the sensor when this is returned.
      */
-    int FACE_ACQUIRED_TOO_CLOSE = 4;
+    public static final int FACE_ACQUIRED_TOO_CLOSE = 4;
 
     /**
      * The detected face is too small, as the user might be too far from the sensor.
      * The user should be informed to move closer to the sensor when this is returned.
      */
-    int FACE_ACQUIRED_TOO_FAR = 5;
+    public static final int FACE_ACQUIRED_TOO_FAR = 5;
 
     /**
      * Only the upper part of the face was detected. The sensor field of view is too high.
      * The user should be informed to move up with respect to the sensor when this is returned.
      */
-    int FACE_ACQUIRED_TOO_HIGH = 6;
+    public static final int FACE_ACQUIRED_TOO_HIGH = 6;
 
     /**
      * Only the lower part of the face was detected. The sensor field of view is too low.
      * The user should be informed to move down with respect to the sensor when this is returned.
      */
-    int FACE_ACQUIRED_TOO_LOW = 7;
+    public static final int FACE_ACQUIRED_TOO_LOW = 7;
 
     /**
      * Only the right part of the face was detected. The sensor field of view is too far right.
      * The user should be informed to move to the right with respect to the sensor
      * when this is returned.
      */
-    int FACE_ACQUIRED_TOO_RIGHT = 8;
+    public static final int FACE_ACQUIRED_TOO_RIGHT = 8;
 
     /**
      * Only the left part of the face was detected. The sensor field of view is too far left.
      * The user should be informed to move to the left with respect to the sensor
      * when this is returned.
      */
-    int FACE_ACQUIRED_TOO_LEFT = 9;
+    public static final int FACE_ACQUIRED_TOO_LEFT = 9;
 
     /**
      * The user's eyes have strayed away from the sensor. If this message is sent, the user should
      * be informed to look at the device. If the user can't be found in the frame, one of the other
      * acquisition messages should be sent, e.g. FACE_ACQUIRED_NOT_DETECTED.
      */
-    int FACE_ACQUIRED_POOR_GAZE = 10;
+    public static final int FACE_ACQUIRED_POOR_GAZE = 10;
 
     /**
      * No face was detected in front of the sensor.
      * The user should be informed to point the sensor to a face when this is returned.
      */
-    int FACE_ACQUIRED_NOT_DETECTED = 11;
+    public static final int FACE_ACQUIRED_NOT_DETECTED = 11;
 
     /**
      * Too much motion was detected.
      * The user should be informed to keep their face steady relative to the
      * sensor.
      */
-    int FACE_ACQUIRED_TOO_MUCH_MOTION = 12;
+    public static final int FACE_ACQUIRED_TOO_MUCH_MOTION = 12;
 
     /**
      * The sensor needs to be re-calibrated. This is an unexpected condition, and should only be
@@ -327,20 +327,20 @@
      * requires user intervention, e.g. re-enrolling. The expected response to this message is to
      * direct the user to re-enroll.
      */
-    int FACE_ACQUIRED_RECALIBRATE = 13;
+    public static final int FACE_ACQUIRED_RECALIBRATE = 13;
 
     /**
      * The face is too different from a previous acquisition. This condition
      * only applies to enrollment. This can happen if the user passes the
      * device to someone else in the middle of enrollment.
      */
-    int FACE_ACQUIRED_TOO_DIFFERENT = 14;
+    public static final int FACE_ACQUIRED_TOO_DIFFERENT = 14;
 
     /**
      * The face is too similar to a previous acquisition. This condition only
      * applies to enrollment. The user should change their pose.
      */
-    int FACE_ACQUIRED_TOO_SIMILAR = 15;
+    public static final int FACE_ACQUIRED_TOO_SIMILAR = 15;
 
     /**
      * The magnitude of the pan angle of the user’s face with respect to the sensor’s
@@ -352,7 +352,7 @@
      *
      * The user should be informed to look more directly at the camera.
      */
-    int FACE_ACQUIRED_PAN_TOO_EXTREME = 16;
+    public static final int FACE_ACQUIRED_PAN_TOO_EXTREME = 16;
 
     /**
      * The magnitude of the tilt angle of the user’s face with respect to the sensor’s
@@ -363,7 +363,7 @@
      *
      * The user should be informed to look more directly at the camera.
      */
-    int FACE_ACQUIRED_TILT_TOO_EXTREME = 17;
+    public static final int FACE_ACQUIRED_TILT_TOO_EXTREME = 17;
 
     /**
      * The magnitude of the roll angle of the user’s face with respect to the sensor’s
@@ -375,7 +375,7 @@
      *
      * The user should be informed to look more directly at the camera.
      */
-    int FACE_ACQUIRED_ROLL_TOO_EXTREME = 18;
+    public static final int FACE_ACQUIRED_ROLL_TOO_EXTREME = 18;
 
     /**
      * The user’s face has been obscured by some object.
@@ -383,7 +383,7 @@
      * The user should be informed to remove any objects from the line of sight from
      * the sensor to the user’s face.
      */
-    int FACE_ACQUIRED_FACE_OBSCURED = 19;
+    public static final int FACE_ACQUIRED_FACE_OBSCURED = 19;
 
     /**
      * This message represents the earliest message sent at the beginning of the authentication
@@ -393,47 +393,47 @@
      * The framework will measure latency based on the time between the last START message and the
      * onAuthenticated callback.
      */
-    int FACE_ACQUIRED_START = 20;
+    public static final int FACE_ACQUIRED_START = 20;
 
     /**
      * The sensor is dirty. The user should be informed to clean the sensor.
      */
-    int FACE_ACQUIRED_SENSOR_DIRTY = 21;
+    public static final int FACE_ACQUIRED_SENSOR_DIRTY = 21;
 
     /**
      * Hardware vendors may extend this list if there are conditions that do not fall under one of
      * the above categories. Vendors are responsible for providing error strings for these errors.
      */
-    int FACE_ACQUIRED_VENDOR = 22;
+    public static final int FACE_ACQUIRED_VENDOR = 22;
 
     /**
      * Unknown acquired code received from the HAL.
      */
-    int FACE_ACQUIRED_UNKNOWN = 23;
+    public static final int FACE_ACQUIRED_UNKNOWN = 23;
 
     /**
      * The first frame from the camera has been received.
      */
-    int FACE_ACQUIRED_FIRST_FRAME_RECEIVED = 24;
+    public static final int FACE_ACQUIRED_FIRST_FRAME_RECEIVED = 24;
 
     /**
      * Dark glasses detected. This can be useful for providing relevant feedback to the user and
      * enabling an alternative authentication logic if the implementation supports it.
      */
-    int FACE_ACQUIRED_DARK_GLASSES_DETECTED = 25;
+    public static final int FACE_ACQUIRED_DARK_GLASSES_DETECTED = 25;
 
     /**
      * A face mask or face covering detected. This can be useful for providing relevant feedback to
      * the user and enabling an alternative authentication logic if the implementation supports it.
      */
-    int FACE_ACQUIRED_MOUTH_COVERING_DETECTED = 26;
+    public static final int FACE_ACQUIRED_MOUTH_COVERING_DETECTED = 26;
 
     /**
      * Vendor codes received from the HAL start at 0. Codes that the framework exposes to keyguard
      * append this value for some reason. We should probably remove this and just send the actual
      * vendor code.
      */
-    int FACE_ACQUIRED_VENDOR_BASE = 1000;
+    public static final int FACE_ACQUIRED_VENDOR_BASE = 1000;
 
 
     /**
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 2592630..d340f3f 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -20,6 +20,44 @@
 import static android.Manifest.permission.MANAGE_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
+import static android.hardware.biometrics.BiometricFaceConstants.BIOMETRIC_ERROR_RE_ENROLL;
+import static android.hardware.biometrics.BiometricFaceConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_DARK_GLASSES_DETECTED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_FACE_OBSCURED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_GOOD;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_INSUFFICIENT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_MOUTH_COVERING_DETECTED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_NOT_DETECTED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_PAN_TOO_EXTREME;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_POOR_GAZE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_RECALIBRATE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_ROLL_TOO_EXTREME;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_SENSOR_DIRTY;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_START;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TILT_TOO_EXTREME;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_CLOSE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DIFFERENT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_FAR;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_MUCH_MOTION;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_SIMILAR;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_CANCELED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_NOT_PRESENT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_NOT_ENROLLED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_NO_SPACE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_USER_CANCELED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_VENDOR;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -29,7 +67,6 @@
 import android.content.pm.PackageManager;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.BiometricFaceConstants;
 import android.hardware.biometrics.BiometricStateListener;
 import android.hardware.biometrics.CryptoObject;
 import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
@@ -58,7 +95,7 @@
  * @hide
  */
 @SystemService(Context.FACE_SERVICE)
-public class FaceManager implements BiometricAuthenticator, BiometricFaceConstants {
+public class FaceManager implements BiometricAuthenticator {
 
     private static final String TAG = "FaceManager";
 
diff --git a/core/java/android/hardware/location/ContextHubClient.java b/core/java/android/hardware/location/ContextHubClient.java
index 01dccd1..953086d 100644
--- a/core/java/android/hardware/location/ContextHubClient.java
+++ b/core/java/android/hardware/location/ContextHubClient.java
@@ -205,14 +205,12 @@
     @FlaggedApi(Flags.FLAG_RELIABLE_MESSAGE)
     public ContextHubTransaction<Void> sendReliableMessageToNanoApp(
             @NonNull NanoAppMessage message) {
-        if (!Flags.reliableMessageImplementation()) {
-            return null;
-        }
-
         ContextHubTransaction<Void> transaction =
                 new ContextHubTransaction<>(ContextHubTransaction.TYPE_RELIABLE_MESSAGE);
 
-        if (!mAttachedHub.supportsReliableMessages()) {
+        if (!Flags.reliableMessageImplementation() ||
+            !mAttachedHub.supportsReliableMessages() ||
+            message.isBroadcastMessage()) {
             transaction.setResponse(new ContextHubTransaction.Response<Void>(
                     ContextHubTransaction.RESULT_FAILED_NOT_SUPPORTED, null));
             return transaction;
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 2b6b358..4512180 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1229,7 +1229,7 @@
         /**
          * Vanilla Ice Cream.
          */
-        public static final int VANILLA_ICE_CREAM = CUR_DEVELOPMENT;
+        public static final int VANILLA_ICE_CREAM = 35;
     }
 
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 90279c6..9f3364f 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -88,6 +88,8 @@
 # PerformanceHintManager
 per-file PerformanceHintManager.java = file:/ADPF_OWNERS
 per-file WorkDuration.java = file:/ADPF_OWNERS
+per-file IHintManager.aidl = file:/ADPF_OWNERS
+per-file IHintSession.aidl = file:/ADPF_OWNERS
 
 # IThermal interfaces
 per-file IThermal* = file:/THERMAL_OWNERS
diff --git a/core/java/android/os/flags.aconfig b/core/java/android/os/flags.aconfig
index fd955e2..e82c4b0 100644
--- a/core/java/android/os/flags.aconfig
+++ b/core/java/android/os/flags.aconfig
@@ -139,6 +139,13 @@
 }
 
 flag {
+    name: "adpf_measure_during_input_event_boost"
+    namespace: "game"
+    description: "Guards use of a boost when view measures during input events"
+    bug: "256549451"
+}
+
+flag {
     name: "battery_service_support_current_adb_command"
     namespace: "backstage_power"
     description: "Whether or not BatteryService supports adb commands for Current values."
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig
index 02e787b..51758aa 100644
--- a/core/java/android/security/flags.aconfig
+++ b/core/java/android/security/flags.aconfig
@@ -43,6 +43,13 @@
 }
 
 flag {
+    name: "unlocked_storage_api"
+    namespace: "hardware_backed_security"
+    description: "Feature flag for unlocked-only storage API"
+    bug: "325129836"
+}
+
+flag {
     name: "deprecate_fsv_sig"
     namespace: "hardware_backed_security"
     description: "Feature flag for deprecating .fsv_sig"
diff --git a/core/java/android/service/dreams/DreamActivity.java b/core/java/android/service/dreams/DreamActivity.java
index a389223..7487d90 100644
--- a/core/java/android/service/dreams/DreamActivity.java
+++ b/core/java/android/service/dreams/DreamActivity.java
@@ -18,9 +18,12 @@
 
 import android.annotation.Nullable;
 import android.app.Activity;
+import android.content.Intent;
 import android.os.Bundle;
 import android.text.TextUtils;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /**
  * The Activity used by the {@link DreamService} to draw screensaver content
  * on the screen. This activity runs in dream application's process, but is started by a
@@ -41,6 +44,7 @@
  *
  * @hide
  */
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
 public class DreamActivity extends Activity {
     static final String EXTRA_CALLBACK = "binder";
     static final String EXTRA_DREAM_TITLE = "title";
@@ -53,19 +57,55 @@
     public void onCreate(@Nullable Bundle bundle) {
         super.onCreate(bundle);
 
-        final String title = getIntent().getStringExtra(EXTRA_DREAM_TITLE);
+        final String title = getTitle(getIntent());
         if (!TextUtils.isEmpty(title)) {
             setTitle(title);
         }
 
-        final Object callback = getIntent().getExtras().getBinder(EXTRA_CALLBACK);
-        if (callback instanceof DreamService.DreamActivityCallbacks) {
-            mCallback = (DreamService.DreamActivityCallbacks) callback;
-            mCallback.onActivityCreated(this);
-        } else {
-            mCallback = null;
+        mCallback = getCallback(getIntent());
+
+        if (mCallback == null) {
             finishAndRemoveTask();
+            return;
         }
+
+        mCallback.onActivityCreated(this);
+    }
+
+    /**
+     * Sets the title of the dream in the intent for starting the {@link DreamActivity}.
+     */
+    public static void setTitle(Intent intent, CharSequence title) {
+        if (TextUtils.isEmpty(title)) {
+            return;
+        }
+
+        intent.putExtra(DreamActivity.EXTRA_DREAM_TITLE, title);
+    }
+
+    /**
+     * Gets the title of the dream from the intent used to start the {@link DreamActivity}.
+     */
+    public static String getTitle(Intent intent) {
+        return intent.getStringExtra(EXTRA_DREAM_TITLE);
+    }
+
+    /**
+     * Sets the dream callback in the intent for starting the {@link DreamActivity}.
+     */
+    public static void setCallback(Intent intent, DreamService.DreamActivityCallbacks callback) {
+        intent.putExtra(DreamActivity.EXTRA_CALLBACK, callback);
+    }
+
+    /**
+     * Retrieves the dream callback from the intent used to start the {@link DreamActivity}.
+     */
+    public static DreamService.DreamActivityCallbacks getCallback(Intent intent) {
+        final Object binder = intent.getExtras().getBinder(EXTRA_CALLBACK);
+
+        return (binder instanceof DreamService.DreamActivityCallbacks)
+                ? (DreamService.DreamActivityCallbacks) binder
+                : null;
     }
 
     @Override
diff --git a/core/java/android/service/dreams/DreamOverlayConnectionHandler.java b/core/java/android/service/dreams/DreamOverlayConnectionHandler.java
index cafe02a..85a13c7 100644
--- a/core/java/android/service/dreams/DreamOverlayConnectionHandler.java
+++ b/core/java/android/service/dreams/DreamOverlayConnectionHandler.java
@@ -39,7 +39,7 @@
  *
  * @hide
  */
-@VisibleForTesting
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
 public final class DreamOverlayConnectionHandler {
     private static final String TAG = "DreamOverlayConnection";
 
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 5da0cb4..17d2790 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -16,6 +16,7 @@
 
 package android.service.dreams;
 
+import android.annotation.FlaggedApi;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
@@ -84,7 +85,14 @@
             mService.comeToFront(this);
         }
 
-        private void onExitRequested() {
+        @Override
+        public void onWakeRequested() {
+            if (Flags.dreamWakeRedirect()) {
+                mService.onWakeRequested();
+            }
+        }
+
+        private void requestExit() {
             try {
                 mDreamOverlayCallback.onExitRequested();
             } catch (RemoteException e) {
@@ -92,6 +100,14 @@
             }
         }
 
+        private void redirectWake(boolean redirect) {
+            try {
+                mDreamOverlayCallback.onRedirectWake(redirect);
+            } catch (RemoteException e) {
+                Log.e(TAG, "could not request redirect wake", e);
+            }
+        }
+
         private boolean shouldShowComplications() {
             return mShowComplications;
         }
@@ -229,7 +245,35 @@
             throw new IllegalStateException("requested exit with no dream present");
         }
 
-        mCurrentClient.onExitRequested();
+        mCurrentClient.requestExit();
+    }
+
+    /**
+     * Called to inform the dream to redirect waking to this overlay rather than exiting.
+     * @param redirect {@code true} if waking up should be redirected. {@code false} otherwise.
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_DREAM_WAKE_REDIRECT)
+    public final void redirectWake(boolean redirect) {
+        if (!Flags.dreamWakeRedirect()) {
+            return;
+        }
+
+        if (mCurrentClient == null) {
+            throw new IllegalStateException("redirected wake with no dream present");
+        }
+
+        mCurrentClient.redirectWake(redirect);
+    }
+
+    /**
+     * Invoked when the dream has requested to exit. This is only called if the dream overlay
+     * has explicitly requested exits to be redirected via {@link #redirectWake(boolean)}.
+     *
+     * @hide
+     */
+    @FlaggedApi(Flags.FLAG_DREAM_WAKE_REDIRECT)
+    public void onWakeRequested() {
     }
 
     /**
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index c26d83c..997c9581 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -41,7 +41,6 @@
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.os.Binder;
 import android.os.Build;
@@ -54,11 +53,9 @@
 import android.os.ServiceManager;
 import android.service.controls.flags.Flags;
 import android.service.dreams.utils.DreamAccessibility;
-import android.util.AttributeSet;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.Slog;
-import android.util.Xml;
 import android.view.ActionMode;
 import android.view.Display;
 import android.view.KeyEvent;
@@ -75,13 +72,10 @@
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.DumpUtils;
 
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.FileDescriptor;
-import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -200,13 +194,6 @@
             "android.service.dreams.DreamService";
 
     /**
-     * The name of the extra where the dream overlay component is stored.
-     * @hide
-     */
-    public static final String EXTRA_DREAM_OVERLAY_COMPONENT =
-            "android.service.dream.DreamService.dream_overlay_component";
-
-    /**
      * Name under which a Dream publishes information about itself.
      * This meta-data must reference an XML resource containing
      * a <code>&lt;{@link android.R.styleable#Dream dream}&gt;</code>
@@ -230,6 +217,7 @@
      * The default value for dream category
      * @hide
      */
+    @VisibleForTesting
     public static final int DREAM_CATEGORY_DEFAULT = 0;
 
     /**
@@ -253,8 +241,14 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface DreamCategory {}
 
+    /**
+     * The name of the extra where the dream overlay component is stored.
+     */
+    static final String EXTRA_DREAM_OVERLAY_COMPONENT =
+            "android.service.dream.DreamService.dream_overlay_component";
+
     private final IDreamManager mDreamManager;
-    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private final Handler mHandler;
     private IBinder mDreamToken;
     private Window mWindow;
     private Activity mActivity;
@@ -287,9 +281,128 @@
 
     private Integer mTrackingConfirmKey = null;
 
+    private boolean mRedirectWake;
+
+    private final Injector mInjector;
+
+    /**
+     * A helper object to inject dependencies into {@link DreamService}.
+     * @hide
+     */
+    @VisibleForTesting
+    public interface Injector {
+        /** Initializes the Injector */
+        void init(Context context);
+
+        /** Creates and returns the dream overlay connection */
+        DreamOverlayConnectionHandler createOverlayConnection(ComponentName overlayComponent);
+
+        /** Returns the {@link DreamActivity} component */
+        ComponentName getDreamActivityComponent();
+
+        /** Returns the dream component */
+        ComponentName getDreamComponent();
+
+        /** Returns the dream package name */
+        String getDreamPackageName();
+
+        /** Returns the {@link DreamManager} */
+        IDreamManager getDreamManager();
+
+        /** Returns the associated service info */
+        ServiceInfo getServiceInfo();
+
+        /** Returns the handler to be used for any posted operation */
+        Handler getHandler();
+
+        /** Returns the package manager */
+        PackageManager getPackageManager();
+
+        /** Returns the resources */
+        Resources getResources();
+    }
+
+    private static final class DefaultInjector implements Injector {
+        private Context mContext;
+        private Class<?> mClassName;
+
+        public void init(Context context) {
+            mContext = context;
+            mClassName = context.getClass();
+        }
+
+        @Override
+        public DreamOverlayConnectionHandler createOverlayConnection(
+                ComponentName overlayComponent) {
+            final Resources resources = mContext.getResources();
+
+            return new DreamOverlayConnectionHandler(
+                    /* context= */ mContext,
+                    Looper.getMainLooper(),
+                    new Intent().setComponent(overlayComponent),
+                    resources.getInteger(R.integer.config_minDreamOverlayDurationMs),
+                    resources.getInteger(R.integer.config_dreamOverlayMaxReconnectAttempts),
+                    resources.getInteger(R.integer.config_dreamOverlayReconnectTimeoutMs));
+        }
+
+        @Override
+        public ComponentName getDreamActivityComponent() {
+            return new ComponentName(mContext, DreamActivity.class);
+        }
+
+        @Override
+        public ComponentName getDreamComponent() {
+            return new ComponentName(mContext, mClassName);
+        }
+
+        @Override
+        public String getDreamPackageName() {
+            return mContext.getApplicationContext().getPackageName();
+        }
+
+        @Override
+        public IDreamManager getDreamManager() {
+            return IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
+        }
+
+        @Override
+        public ServiceInfo getServiceInfo() {
+            return fetchServiceInfo(mContext, getDreamComponent());
+        }
+
+        @Override
+        public Handler getHandler() {
+            return new Handler(Looper.getMainLooper());
+        }
+
+        @Override
+        public PackageManager getPackageManager() {
+            return mContext.getPackageManager();
+        }
+
+        @Override
+        public Resources getResources() {
+            return mContext.getResources();
+        }
+
+    }
 
     public DreamService() {
-        mDreamManager = IDreamManager.Stub.asInterface(ServiceManager.getService(DREAM_SERVICE));
+        this(new DefaultInjector());
+    }
+
+    /**
+     * Constructor for test purposes.
+     *
+     * @param injector used for providing dependencies
+     * @hide
+     */
+    @VisibleForTesting
+    public DreamService(Injector injector) {
+        mInjector = injector;
+        mInjector.init(this);
+        mDreamManager = mInjector.getDreamManager();
+        mHandler = mInjector.getHandler();
     }
 
     /**
@@ -997,15 +1110,20 @@
     public void onCreate() {
         if (mDebug) Slog.v(mTag, "onCreate()");
 
-        mDreamComponent = new ComponentName(this, getClass());
-        mShouldShowComplications = fetchShouldShowComplications(this /*context*/,
-                fetchServiceInfo(this /*context*/, mDreamComponent));
+        mDreamComponent = mInjector.getDreamComponent();
+        mShouldShowComplications = fetchShouldShowComplications(mInjector.getPackageManager(),
+                mInjector.getServiceInfo());
         mOverlayCallback = new IDreamOverlayCallback.Stub() {
             @Override
             public void onExitRequested() {
                 // Simply finish dream when exit is requested.
                 mHandler.post(() -> finish());
             }
+
+            @Override
+            public void onRedirectWake(boolean redirect) {
+                mRedirectWake = redirect;
+            }
         };
 
         super.onCreate();
@@ -1066,16 +1184,7 @@
 
         // Connect to the overlay service if present.
         if (!mWindowless && overlayComponent != null) {
-            final Resources resources = getResources();
-            final Intent overlayIntent = new Intent().setComponent(overlayComponent);
-
-            mOverlayConnection = new DreamOverlayConnectionHandler(
-                    /* context= */ this,
-                    Looper.getMainLooper(),
-                    overlayIntent,
-                    resources.getInteger(R.integer.config_minDreamOverlayDurationMs),
-                    resources.getInteger(R.integer.config_dreamOverlayMaxReconnectAttempts),
-                    resources.getInteger(R.integer.config_dreamOverlayReconnectTimeoutMs));
+            mOverlayConnection = mInjector.createOverlayConnection(overlayComponent);
 
             if (!mOverlayConnection.bind()) {
                 // Binding failed.
@@ -1181,6 +1290,18 @@
                     + ", mFinished=" + mFinished);
         }
 
+        if (!fromSystem && mOverlayConnection != null && mRedirectWake) {
+            mOverlayConnection.addConsumer(overlay -> {
+                try {
+                    overlay.onWakeRequested();
+                } catch (RemoteException e) {
+                    Log.e(mTag, "could not inform overlay of dream wakeup:" + e);
+                }
+            });
+
+            return;
+        }
+
         if (!mWaking && !mFinished) {
             mWaking = true;
 
@@ -1242,11 +1363,25 @@
     @TestApi
     public static DreamMetadata getDreamMetadata(@NonNull Context context,
             @Nullable ServiceInfo serviceInfo) {
+        return getDreamMetadata(context.getPackageManager(), serviceInfo);
+    }
+
+    /**
+     * Parses and returns metadata of the dream service indicated by the service info. Returns null
+     * if metadata cannot be found.
+     *
+     * Note that {@link ServiceInfo} must be fetched with {@link PackageManager#GET_META_DATA} flag.
+     *
+     * @hide
+     */
+    @Nullable
+    public static DreamMetadata getDreamMetadata(@NonNull PackageManager packageManager,
+            @Nullable ServiceInfo serviceInfo) {
         if (serviceInfo == null) return null;
 
-        final PackageManager pm = context.getPackageManager();
-
-        try (TypedArray rawMetadata = readMetadata(pm, serviceInfo)) {
+        try (TypedArray rawMetadata = packageManager.extractPackageItemInfoAttributes(serviceInfo,
+                DreamService.DREAM_META_DATA, DREAM_META_DATA_ROOT_TAG,
+                com.android.internal.R.styleable.Dream)) {
             if (rawMetadata == null) return null;
             return new DreamMetadata(
                     convertToComponentName(
@@ -1261,47 +1396,6 @@
         }
     }
 
-    /**
-     * Returns the raw XML metadata fetched from the {@link ServiceInfo}.
-     *
-     * Returns <code>null</code> if the {@link ServiceInfo} doesn't contain valid dream metadata.
-     */
-    @Nullable
-    private static TypedArray readMetadata(PackageManager pm, ServiceInfo serviceInfo) {
-        if (serviceInfo == null || serviceInfo.metaData == null) {
-            return null;
-        }
-
-        try (XmlResourceParser parser =
-                     serviceInfo.loadXmlMetaData(pm, DreamService.DREAM_META_DATA)) {
-            if (parser == null) {
-                if (DEBUG) Log.w(TAG, "No " + DreamService.DREAM_META_DATA + " metadata");
-                return null;
-            }
-
-            final AttributeSet attrs = Xml.asAttributeSet(parser);
-            while (true) {
-                final int type = parser.next();
-                if (type == XmlPullParser.END_DOCUMENT || type == XmlPullParser.START_TAG) {
-                    break;
-                }
-            }
-
-            if (!parser.getName().equals(DREAM_META_DATA_ROOT_TAG)) {
-                if (DEBUG) {
-                    Log.w(TAG, "Metadata does not start with " + DREAM_META_DATA_ROOT_TAG + " tag");
-                }
-                return null;
-            }
-
-            return pm.getResourcesForApplication(serviceInfo.applicationInfo).obtainAttributes(
-                    attrs, com.android.internal.R.styleable.Dream);
-        } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) {
-            if (DEBUG) Log.e(TAG, "Error parsing: " + serviceInfo.packageName, e);
-            return null;
-        }
-    }
-
     @Nullable
     private static ComponentName convertToComponentName(@Nullable String flattenedString,
             ServiceInfo serviceInfo) {
@@ -1406,14 +1500,16 @@
         // for the DreamActivity to report onActivityCreated via
         // DreamServiceWrapper.onActivityCreated.
         if (!mWindowless) {
-            Intent i = new Intent(this, DreamActivity.class);
-            i.setPackage(getApplicationContext().getPackageName());
+            Intent i = new Intent();
+            i.setComponent(mInjector.getDreamActivityComponent());
+            i.setPackage(mInjector.getDreamPackageName());
             i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_USER_ACTION);
-            i.putExtra(DreamActivity.EXTRA_CALLBACK, new DreamActivityCallbacks(mDreamToken));
-            final ServiceInfo serviceInfo = fetchServiceInfo(this,
-                    new ComponentName(this, getClass()));
-            i.putExtra(DreamActivity.EXTRA_DREAM_TITLE,
-                    fetchDreamLabel(this, serviceInfo, isPreviewMode));
+            DreamActivity.setCallback(i, new DreamActivityCallbacks(mDreamToken));
+            final ServiceInfo serviceInfo = mInjector.getServiceInfo();
+            final CharSequence title = fetchDreamLabel(mInjector.getPackageManager(),
+                    mInjector.getResources(), serviceInfo, isPreviewMode);
+
+            DreamActivity.setTitle(i, title);
 
             try {
                 mDreamManager.startDreamActivity(i);
@@ -1539,9 +1635,9 @@
      * the dream should show complications on the overlay. If not defined, returns
      * {@link DreamService#DEFAULT_SHOW_COMPLICATIONS}.
      */
-    private static boolean fetchShouldShowComplications(Context context,
+    private static boolean fetchShouldShowComplications(@NonNull PackageManager packageManager,
             @Nullable ServiceInfo serviceInfo) {
-        final DreamMetadata metadata = getDreamMetadata(context, serviceInfo);
+        final DreamMetadata metadata = getDreamMetadata(packageManager, serviceInfo);
         if (metadata != null) {
             return metadata.showComplications;
         }
@@ -1549,19 +1645,20 @@
     }
 
     @Nullable
-    private static CharSequence fetchDreamLabel(Context context,
+    private static CharSequence fetchDreamLabel(
+            PackageManager pm,
+            Resources resources,
             @Nullable ServiceInfo serviceInfo,
             boolean isPreviewMode) {
         if (serviceInfo == null) {
             return null;
         }
-        final PackageManager pm = context.getPackageManager();
         final CharSequence dreamLabel = serviceInfo.loadLabel(pm);
         if (!isPreviewMode || dreamLabel == null) {
             return dreamLabel;
         }
         // When in preview mode, return a special label indicating the dream is in preview.
-        return context.getResources().getString(R.string.dream_preview_title, dreamLabel);
+        return resources.getString(R.string.dream_preview_title, dreamLabel);
     }
 
     @Nullable
@@ -1643,14 +1740,16 @@
     }
 
     /** @hide */
-    final class DreamActivityCallbacks extends Binder {
+    @VisibleForTesting
+    public final class DreamActivityCallbacks extends Binder {
         private final IBinder mActivityDreamToken;
 
         DreamActivityCallbacks(IBinder token) {
             mActivityDreamToken = token;
         }
 
-        void onActivityCreated(DreamActivity activity) {
+        /** Callback when the {@link DreamActivity} has been created */
+        public void onActivityCreated(DreamActivity activity) {
             if (mActivityDreamToken != mDreamToken || mFinished) {
                 Slog.d(TAG, "DreamActivity was created after the dream was finished or "
                         + "a new dream started, finishing DreamActivity");
@@ -1672,8 +1771,8 @@
             onWindowCreated(activity.getWindow());
         }
 
-        // If DreamActivity is destroyed, wake up from Dream.
-        void onActivityDestroyed() {
+        /** Callback when the {@link DreamActivity} has been destroyed */
+        public void onActivityDestroyed() {
             mActivity = null;
             mWindow = null;
             detach();
@@ -1685,6 +1784,7 @@
      *
      * @hide
      */
+    @VisibleForTesting
     @TestApi
     public static final class DreamMetadata {
         @Nullable
@@ -1700,7 +1800,11 @@
         @FlaggedApi(Flags.FLAG_HOME_PANEL_DREAM)
         public final int dreamCategory;
 
-        DreamMetadata(
+        /**
+         * @hide
+         */
+        @VisibleForTesting
+        public DreamMetadata(
                 ComponentName settingsActivity,
                 Drawable previewImage,
                 boolean showComplications,
@@ -1715,4 +1819,14 @@
             }
         }
     }
+
+    /**
+     * Sets the dream overlay component to be used by the dream.
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public static void setDreamOverlayComponent(Intent intent, ComponentName component) {
+        intent.putExtra(DreamService.EXTRA_DREAM_OVERLAY_COMPONENT, component);
+    }
 }
diff --git a/core/java/android/service/dreams/IDreamOverlayCallback.aidl b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
index ec76a33..fae4780 100644
--- a/core/java/android/service/dreams/IDreamOverlayCallback.aidl
+++ b/core/java/android/service/dreams/IDreamOverlayCallback.aidl
@@ -23,9 +23,14 @@
 *
 * @hide
 */
-interface IDreamOverlayCallback {
+oneway interface IDreamOverlayCallback {
     /**
     * Invoked to request the dream exit.
     */
     void onExitRequested();
+
+    /**
+    * Invoked to redirect wake requests to overlay instead.
+    */
+    void onRedirectWake(boolean redirect);
 }
\ No newline at end of file
diff --git a/core/java/android/service/dreams/IDreamOverlayClient.aidl b/core/java/android/service/dreams/IDreamOverlayClient.aidl
index 5054d4d..0eb15a0 100644
--- a/core/java/android/service/dreams/IDreamOverlayClient.aidl
+++ b/core/java/android/service/dreams/IDreamOverlayClient.aidl
@@ -43,6 +43,9 @@
     /** Called when the dream has ended. */
     void endDream();
 
+    /** Called when wake up has been redirected to the overlay. */
+    void onWakeRequested();
+
     /** Called when the dream is coming to the front. */
     void comeToFront();
 }
diff --git a/core/java/android/service/dreams/flags.aconfig b/core/java/android/service/dreams/flags.aconfig
index 0a458bc..f87cb85 100644
--- a/core/java/android/service/dreams/flags.aconfig
+++ b/core/java/android/service/dreams/flags.aconfig
@@ -21,6 +21,14 @@
 }
 
 flag {
+  name: "dream_wake_redirect"
+  namespace: "systemui"
+  description: "This flag enables using a host to handle displaying a dream's overlay rather than "
+      "relying on the dream's window"
+  bug: "334083490"
+}
+
+flag {
   name: "dream_tracks_focus"
   namespace: "communal"
   description: "This flag enables the ability for dreams to track whether or not they have focus"
diff --git a/core/java/android/tracing/flags.aconfig b/core/java/android/tracing/flags.aconfig
index c50c384..74428aa 100644
--- a/core/java/android/tracing/flags.aconfig
+++ b/core/java/android/tracing/flags.aconfig
@@ -22,3 +22,11 @@
     description: "Migrate IME tracing to Perfetto"
     bug: "276433199"
 }
+
+flag {
+    name: "perfetto_ime"
+    namespace: "windowing_tools"
+    description: "Migrate IME tracing to Perfetto"
+    is_fixed_read_only: true
+    bug: "276433199"
+}
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index a150187..55ad4ae 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -17,11 +17,13 @@
 package android.view;
 
 import android.app.ActivityManager;
-import android.view.IRemoteAnimationFinishedCallback;
-import android.view.SurfaceControl;
 import android.graphics.GraphicBuffer;
+import android.view.IRemoteAnimationFinishedCallback;
+import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
 import android.window.PictureInPictureSurfaceTransaction;
 import android.window.TaskSnapshot;
+import android.window.WindowAnimationState;
 
 import com.android.internal.os.IResultReceiver;
 
@@ -160,4 +162,17 @@
      * @param duration the duration of the app launch animation
      */
     void animateNavigationBarToApp(long duration);
+
+    /**
+     * Hand off the ongoing animation of a set of remote targets, to be run by another handler using
+     * the given starting parameters.
+     *
+     * Once the handoff is complete, operations on the old leashes for the given targets as well as
+     * callbacks will become no-ops.
+     *
+     * The number of targets MUST match the number of states, and each state MUST match the target
+     * at the same index.
+     */
+    oneway void handOffAnimation(in RemoteAnimationTarget[] targets,
+                    in WindowAnimationState[] states);
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2a1eb97..e7c1885 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -160,6 +160,7 @@
 import android.util.SparseIntArray;
 import android.util.StateSet;
 import android.util.SuperNotCalledException;
+import android.util.TimeUtils;
 import android.util.TypedValue;
 import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
 import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
@@ -2429,12 +2430,6 @@
     public static final int FRAME_RATE_CATEGORY_REASON_VELOCITY = 0x0600_0000;
 
     /**
-     * This indicates that the frame rate category was chosen because it is idle.
-     * @hide
-     */
-    public static final int FRAME_RATE_CATEGORY_REASON_IDLE = 0x0700_0000;
-
-    /**
      * This indicates that the frame rate category was chosen because it is currently boosting.
      * @hide
      */
@@ -4744,6 +4739,11 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     protected int mLeft;
     /**
+     * The mLeft from the previous frame. Used for detecting movement for purposes of variable
+     * refresh rate.
+     */
+    private int mLastFrameLeft;
+    /**
      * The distance in pixels from the left edge of this view's parent
      * to the right edge of this view.
      * {@hide}
@@ -4760,6 +4760,11 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     protected int mTop;
     /**
+     * The mTop from the previous frame. Used for detecting movement for purposes of variable
+     * refresh rate.
+     */
+    private int mLastFrameTop;
+    /**
      * The distance in pixels from the top edge of this view's parent
      * to the bottom edge of this view.
      * {@hide}
@@ -18097,6 +18102,24 @@
     }
 
     /**
+     * Called by {@link #measure(int, int)} to check if the current frame presentation got
+     * delayed by an expensive view mesures during the input event dispatching. (e.g. scrolling)
+     */
+    private boolean hasExpensiveMeasuresDuringInputEvent() {
+        final AttachInfo attachInfo = mAttachInfo;
+        if (attachInfo == null || attachInfo.mRootView == null) {
+            return false;
+        }
+        if (!attachInfo.mHandlingPointerEvent) {
+            return false;
+        }
+        final ViewFrameInfo info = attachInfo.mViewRootImpl.mViewFrameInfo;
+        final long durationFromVsyncTimeMs = (System.nanoTime()
+                - Choreographer.getInstance().getLastFrameTimeNanos()) / TimeUtils.NANOS_PER_MS;
+        return durationFromVsyncTimeMs > 3L || info.getAndIncreaseViewMeasuredCount() > 10;
+    }
+
+    /**
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -19516,7 +19539,6 @@
      */
     public final void setTop(int top) {
         if (top != mTop) {
-            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
             final boolean matrixIsIdentity = hasIdentityMatrix();
             if (matrixIsIdentity) {
                 if (mAttachInfo != null) {
@@ -20408,7 +20430,6 @@
      */
     public void offsetTopAndBottom(int offset) {
         if (offset != 0) {
-            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
             final boolean matrixIsIdentity = hasIdentityMatrix();
             if (matrixIsIdentity) {
                 if (isHardwareAccelerated()) {
@@ -20460,7 +20481,6 @@
      */
     public void offsetLeftAndRight(int offset) {
         if (offset != 0) {
-            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
             final boolean matrixIsIdentity = hasIdentityMatrix();
             if (matrixIsIdentity) {
                 if (isHardwareAccelerated()) {
@@ -25504,7 +25524,6 @@
         }
 
         if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
-            mPrivateFlags4 |= PFLAG4_HAS_MOVED;
             changed = true;
 
             // Remember our drawn bit
@@ -28116,6 +28135,15 @@
                 if (isTraversalTracingEnabled()) {
                     Trace.beginSection(mTracingStrings.onMeasure);
                 }
+                if (android.os.Flags.adpfMeasureDuringInputEventBoost()) {
+                    final boolean notifyRenderer = hasExpensiveMeasuresDuringInputEvent();
+                    if (notifyRenderer) {
+                        Trace.traceBegin(Trace.TRACE_TAG_VIEW,
+                                "CPU_LOAD_UP: " + "hasExpensiveMeasuresDuringInputEvent");
+                        getViewRootImpl().notifyRendererOfExpensiveFrame();
+                        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+                    }
+                }
                 // measure ourselves, this should set the measured dimension flag back
                 onMeasure(widthMeasureSpec, heightMeasureSpec);
                 if (isTraversalTracingEnabled()) {
@@ -33942,14 +33970,15 @@
             return; // can't vote if not connected
         }
         float velocity = mFrameContentVelocity;
-        float frameRate = mPreferredFrameRate;
+        final float frameRate = mPreferredFrameRate;
         ViewParent parent = mParent;
         if (velocity <= 0 && Float.isNaN(frameRate)) {
             // The most common case is when nothing is set, so this special case is called
             // often.
             if (mAttachInfo.mViewVelocityApi
-                    && (mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
-                    PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)
+                    && ((mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
+                    PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN) || mLastFrameLeft != mLeft
+                    || mLastFrameTop != mTop)
                     && viewRootImpl.shouldCheckFrameRate(false)
                     && parent instanceof View
                     && ((View) parent).mFrameContentVelocity <= 0) {
@@ -33962,14 +33991,17 @@
                 viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
                 mLastFrameRateCategory = frameRateCategory;
             }
+            mLastFrameLeft = mLeft;
+            mLastFrameTop = mTop;
             return;
         }
         if (viewRootImpl.shouldCheckFrameRate(frameRate > 0f)) {
             float velocityFrameRate = 0f;
             if (mAttachInfo.mViewVelocityApi) {
                 if (velocity < 0f
-                        && (mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
-                        PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)
+                        && ((mPrivateFlags4 & (PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN)) == (
+                        PFLAG4_HAS_MOVED | PFLAG4_HAS_DRAWN) || mLastFrameLeft != mLeft
+                        || mLastFrameTop != mTop)
                         && mParent instanceof View
                         && ((View) mParent).mFrameContentVelocity <= 0
                 ) {
@@ -33982,13 +34014,15 @@
             }
             if (velocityFrameRate > 0f || frameRate > 0f) {
                 int compatibility;
+                float frameRateToSet;
                 if (frameRate >= velocityFrameRate) {
                     compatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
+                    frameRateToSet = frameRate;
                 } else {
                     compatibility = FRAME_RATE_COMPATIBILITY_GTE;
-                    frameRate = velocityFrameRate;
+                    frameRateToSet = velocityFrameRate;
                 }
-                viewRootImpl.votePreferredFrameRate(frameRate, compatibility);
+                viewRootImpl.votePreferredFrameRate(frameRateToSet, compatibility);
             }
         }
 
@@ -34032,6 +34066,8 @@
             viewRootImpl.votePreferredFrameRateCategory(category, reason, this);
             mLastFrameRateCategory = frameRateCategory;
         }
+        mLastFrameLeft = mLeft;
+        mLastFrameTop = mTop;
     }
 
     private float convertVelocityToFrameRate(float velocityPps) {
@@ -34052,7 +34088,7 @@
      */
     @FlaggedApi(FLAG_VIEW_VELOCITY_API)
     public void setFrameContentVelocity(float pixelsPerSecond) {
-        if (viewVelocityApi()) {
+        if (mAttachInfo != null && mAttachInfo.mViewVelocityApi) {
             mFrameContentVelocity = Math.abs(pixelsPerSecond);
 
             if (sToolkitMetricsForFrameRateDecisionFlagValue) {
@@ -34070,8 +34106,8 @@
      */
     @FlaggedApi(FLAG_VIEW_VELOCITY_API)
     public float getFrameContentVelocity() {
-        if (viewVelocityApi()) {
-            return (mFrameContentVelocity < 0f) ? 0f : mFrameContentVelocity;
+        if (mAttachInfo != null && mAttachInfo.mViewVelocityApi) {
+            return Math.max(mFrameContentVelocity, 0f);
         }
         return 0;
     }
diff --git a/core/java/android/view/ViewFrameInfo.java b/core/java/android/view/ViewFrameInfo.java
index 36bf532..46f1472 100644
--- a/core/java/android/view/ViewFrameInfo.java
+++ b/core/java/android/view/ViewFrameInfo.java
@@ -34,6 +34,8 @@
 
     private int mInputEventId;
 
+    private int mViewsMeasuredCounts;
+
     /**
      * Populate the missing fields using the data from ViewFrameInfo
      * @param frameInfo : the structure FrameInfo object to populate
@@ -51,6 +53,7 @@
         drawStart = 0;
         mInputEventId = IInputConstants.INVALID_INPUT_EVENT_ID;
         flags = 0;
+        mViewsMeasuredCounts = 0;
     }
 
     /**
@@ -61,6 +64,13 @@
     }
 
     /**
+     * Record the number of view being measured for the current frame.
+     */
+    public int getAndIncreaseViewMeasuredCount() {
+        return ++mViewsMeasuredCounts;
+    }
+
+    /**
      * Assign the value for input event id
      * @param eventId the id of the input event
      */
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 52ff142..11ad86c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -49,7 +49,6 @@
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.os.SystemClock;
-import android.service.autofill.Flags;
 import android.util.AttributeSet;
 import android.util.IntArray;
 import android.util.Log;
@@ -2652,10 +2651,12 @@
 
             // Check for interception.
             final boolean intercepted;
-            if (actionMasked == MotionEvent.ACTION_DOWN
-                    || mFirstTouchTarget != null) {
+            ViewRootImpl viewRootImpl = getViewRootImpl();
+            if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {
                 final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
-                if (!disallowIntercept) {
+                final boolean isDispatchingBack = (viewRootImpl != null
+                        && viewRootImpl.getOnBackInvokedDispatcher().isDispatching());
+                if (!disallowIntercept || isDispatchingBack) { // Allow back to intercept touch
                     intercepted = onInterceptTouchEvent(ev);
                     ev.setAction(action); // restore action in case it was changed
                 } else {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 84cde0d..2cb862c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -37,7 +37,6 @@
 import static android.view.Surface.FRAME_RATE_COMPATIBILITY_GTE;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_BOOST;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_CONFLICTED;
-import static android.view.View.FRAME_RATE_CATEGORY_REASON_IDLE;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_INTERMITTENT;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_INVALID;
 import static android.view.View.FRAME_RATE_CATEGORY_REASON_LARGE;
@@ -74,6 +73,7 @@
 import static android.view.ViewRootImplProto.WINDOW_ATTRIBUTES;
 import static android.view.ViewRootImplProto.WIN_FRAME;
 import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE;
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
 import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -1087,16 +1087,10 @@
     // The last preferred frame rate of the view that is mainly used to
     // track the difference between the current preferred frame rate and the previous value.
     private float mLastPreferredFrameRate = 0;
-    // Used to check if there were any view invalidations in
-    // the previous time frame (FRAME_RATE_IDLENESS_REEVALUATE_TIME).
-    private boolean mHasInvalidation = false;
     // Used to check if it is in the frame rate boosting period.
     private boolean mIsFrameRateBoosting = false;
     // Used to check if it is in touch boosting period.
     private boolean mIsTouchBoosting = false;
-    // Used to check if there is a message in the message queue
-    // for idleness handling.
-    private boolean mHasIdledMessage = false;
     private boolean mDrawnThisFrame = false;
     // Used to check if there is a conflict between different frame rate voting.
     // Take 24 and 30 as an example, 24 is not a divisor of 30.
@@ -1107,10 +1101,6 @@
             FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
     // time for touch boost period.
     private static final int FRAME_RATE_TOUCH_BOOST_TIME = 3000;
-    // time for checking idle status periodically.
-    private static final int FRAME_RATE_IDLENESS_CHECK_TIME_MILLIS = 500;
-    // time for revaluating the idle status before lowering the frame rate.
-    private static final int FRAME_RATE_IDLENESS_REEVALUATE_TIME = 1000;
     // time for evaluating the interval between current time and
     // the time when frame rate was set previously.
     private static final int FRAME_RATE_SETTING_REEVALUATE_TIME = 100;
@@ -1282,7 +1272,7 @@
         mImeFocusController = new ImeFocusController(this);
 
         mScrollCaptureRequestTimeout = SCROLL_CAPTURE_REQUEST_TIMEOUT_MILLIS;
-        mOnBackInvokedDispatcher = new WindowOnBackInvokedDispatcher(context);
+        mOnBackInvokedDispatcher = new WindowOnBackInvokedDispatcher(context, Looper.myLooper());
         if (sensitiveContentAppProtection()) {
             mSensitiveContentProtectionService =
                     ISensitiveContentProtectionManager.Stub.asInterface(
@@ -2141,7 +2131,8 @@
 
     private int adjustLayoutInDisplayCutoutMode(WindowManager.LayoutParams attrs) {
         final int originalMode = attrs.layoutInDisplayCutoutMode;
-        if ((attrs.privateFlags & PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED) != 0
+        if ((attrs.privateFlags & (PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED
+                | PRIVATE_FLAG_OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE)) != 0
                 && attrs.isFullscreen()
                 && attrs.getFitInsetsTypes() == 0
                 && attrs.getFitInsetsSides() == 0) {
@@ -4261,7 +4252,6 @@
                 mHandler.sendEmptyMessageDelayed(MSG_FRAME_RATE_SETTING,
                         FRAME_RATE_SETTING_REEVALUATE_TIME);
             }
-            checkIdleness();
             mFrameRateCategoryHighCount = mFrameRateCategoryHighCount > 0
                     ? mFrameRateCategoryHighCount - 1 : mFrameRateCategoryHighCount;
             mFrameRateCategoryNormalCount = mFrameRateCategoryNormalCount > 0
@@ -6443,8 +6433,6 @@
                     return "MSG_REFRESH_POINTER_ICON";
                 case MSG_TOUCH_BOOST_TIMEOUT:
                     return "MSG_TOUCH_BOOST_TIMEOUT";
-                case MSG_CHECK_INVALIDATION_IDLE:
-                    return "MSG_CHECK_INVALIDATION_IDLE";
                 case MSG_FRAME_RATE_SETTING:
                     return "MSG_FRAME_RATE_SETTING";
             }
@@ -6712,27 +6700,6 @@
                     mIsFrameRateBoosting = false;
                     mIsTouchBoosting = false;
                     break;
-                case MSG_CHECK_INVALIDATION_IDLE:
-                    if (!mHasInvalidation && !mIsFrameRateBoosting && !mIsTouchBoosting) {
-                        mPreferredFrameRateCategory = FRAME_RATE_CATEGORY_NO_PREFERENCE;
-                        mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_IDLE;
-                        mFrameRateCategoryView = null;
-                        setPreferredFrameRateCategory(mPreferredFrameRateCategory);
-                        mHasIdledMessage = false;
-                    } else {
-                        /**
-                         * If there is no invalidation within a certain period,
-                         * we consider the display is idled.
-                         * We then set the frame rate catetogry to NO_PREFERENCE.
-                         * Note that SurfaceFlinger also has a mechanism to lower the refresh rate
-                         * if there is no updates of the buffer.
-                         */
-                        mHasInvalidation = false;
-                        mHandler.sendEmptyMessageDelayed(MSG_CHECK_INVALIDATION_IDLE,
-                                FRAME_RATE_IDLENESS_REEVALUATE_TIME);
-                        mHasIdledMessage = true;
-                    }
-                    break;
                 case MSG_REFRESH_POINTER_ICON:
                     if (mPointerIconEvent == null) {
                         break;
@@ -6742,7 +6709,6 @@
                 case MSG_FRAME_RATE_SETTING:
                     mPreferredFrameRate = 0;
                     mFrameRateCompatibility = FRAME_RATE_COMPATIBILITY_FIXED_SOURCE;
-                    setPreferredFrameRate(mPreferredFrameRate);
                     break;
             }
         }
@@ -12647,7 +12613,6 @@
             case FRAME_RATE_CATEGORY_REASON_REQUESTED -> str = "requested";
             case FRAME_RATE_CATEGORY_REASON_INVALID -> str = "invalid frame rate";
             case FRAME_RATE_CATEGORY_REASON_VELOCITY -> str = "velocity";
-            case FRAME_RATE_CATEGORY_REASON_IDLE -> str = "idle";
             case FRAME_RATE_CATEGORY_REASON_UNKNOWN -> str = "unknown";
             case FRAME_RATE_CATEGORY_REASON_BOOST -> str = "boost";
             case FRAME_RATE_CATEGORY_REASON_TOUCH -> str = "touch";
@@ -12716,7 +12681,6 @@
             mFrameRateCategoryChangeReason = reason;
             // mFrameRateCategoryView = view == null ? "-" : view.getClass().getSimpleName();
         }
-        mHasInvalidation = true;
         mDrawnThisFrame = true;
     }
 
@@ -12790,7 +12754,6 @@
                 mFrameRateCategoryHighCount = FRAME_RATE_CATEGORY_COUNT;
                 mFrameRateCategoryChangeReason = FRAME_RATE_CATEGORY_REASON_VELOCITY;
                 mFrameRateCategoryView = null;
-                mHasInvalidation = true;
                 mDrawnThisFrame = true;
                 return;
             }
@@ -12822,7 +12785,6 @@
 
         mPreferredFrameRate = nextFrameRate;
         mFrameRateCompatibility = nextFrameRateCompatibility;
-        mHasInvalidation = true;
         mDrawnThisFrame = true;
     }
 
@@ -12942,19 +12904,8 @@
         return false;
     }
 
-    private void checkIdleness() {
-        if (!mHasIdledMessage) {
-            // Check where the display is idled periodically.
-            // If so, set the frame rate category to NO_PREFERENCE
-            mHandler.sendEmptyMessageDelayed(MSG_CHECK_INVALIDATION_IDLE,
-                    FRAME_RATE_IDLENESS_CHECK_TIME_MILLIS);
-            mHasIdledMessage = true;
-        }
-    }
-
     private void removeVrrMessages() {
         mHandler.removeMessages(MSG_TOUCH_BOOST_TIMEOUT);
-        mHandler.removeMessages(MSG_CHECK_INVALIDATION_IDLE);
         mHandler.removeMessages(MSG_FRAME_RATE_SETTING);
     }
 
@@ -12974,7 +12925,8 @@
         mMinusOneFrameIntervalMillis = timeIntervalMillis;
 
         mLastUpdateTimeMillis = currentTimeMillis;
-        if (timeIntervalMillis >= INFREQUENT_UPDATE_INTERVAL_MILLIS) {
+        if (timeIntervalMillis + mMinusTwoFrameIntervalMillis
+                >= INFREQUENT_UPDATE_INTERVAL_MILLIS) {
             int infrequentUpdateCount = mInfrequentUpdateCount;
             mInfrequentUpdateCount = infrequentUpdateCount == INFREQUENT_UPDATE_COUNTS
                     ? infrequentUpdateCount : infrequentUpdateCount + 1;
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index afe5b7e..0bc2430 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -3386,6 +3386,12 @@
         public static final int PRIVATE_FLAG_IMMERSIVE_CONFIRMATION_WINDOW = 1 << 17;
 
         /**
+         * Flag to indicate that the window is forcibly to layout under the display cutout.
+         * @hide
+         */
+        public static final int PRIVATE_FLAG_OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE = 1 << 18;
+
+        /**
          * Flag to indicate that any window added by an application process that is of type
          * {@link #TYPE_TOAST} or that requires
          * {@link android.app.AppOpsManager#OP_SYSTEM_ALERT_WINDOW} permission should be hidden when
@@ -3505,6 +3511,7 @@
                 PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS,
                 PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE,
                 PRIVATE_FLAG_IMMERSIVE_CONFIRMATION_WINDOW,
+                PRIVATE_FLAG_OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE,
                 SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
                 PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY,
                 PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION,
@@ -3587,6 +3594,10 @@
                         equals = PRIVATE_FLAG_IMMERSIVE_CONFIRMATION_WINDOW,
                         name = "IMMERSIVE_CONFIRMATION_WINDOW"),
                 @ViewDebug.FlagToString(
+                        mask = PRIVATE_FLAG_OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE,
+                        equals = PRIVATE_FLAG_OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE,
+                        name = "OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE"),
+                @ViewDebug.FlagToString(
                         mask = SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
                         equals = SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
                         name = "HIDE_NON_SYSTEM_OVERLAY_WINDOWS"),
diff --git a/core/java/android/view/flags/refresh_rate_flags.aconfig b/core/java/android/view/flags/refresh_rate_flags.aconfig
index d0fe3e0..e3054da 100644
--- a/core/java/android/view/flags/refresh_rate_flags.aconfig
+++ b/core/java/android/view/flags/refresh_rate_flags.aconfig
@@ -61,7 +61,7 @@
     name: "toolkit_frame_rate_default_normal_read_only"
     namespace: "toolkit"
     description: "Feature flag for setting frame rate category as NORMAL for default"
-    bug: "239979904"
+    bug: "335874198"
     is_fixed_read_only: true
 }
 
@@ -69,7 +69,7 @@
     name: "toolkit_frame_rate_by_size_read_only"
     namespace: "toolkit"
     description: "Feature flag for setting frame rate category based on size"
-    bug: "239979904"
+    bug: "335874198"
     is_fixed_read_only: true
 }
 
@@ -77,7 +77,7 @@
     name: "toolkit_frame_rate_velocity_mapping_read_only"
     namespace: "toolkit"
     description: "Feature flag for setting frame rate based on velocity"
-    bug: "239979904"
+    bug: "335874198"
     is_fixed_read_only: true
 }
 
@@ -85,7 +85,7 @@
     name: "toolkit_frame_rate_small_uses_percent_read_only"
     namespace: "toolkit"
     description: "VRR uses percent of size to consider a view to be small"
-    bug: "239979904"
+    bug: "335874198"
     is_fixed_read_only: true
 }
 
@@ -93,7 +93,7 @@
     name: "toolkit_frame_rate_typing_read_only"
     namespace: "toolkit"
     description: "Feature flag for suppressing boost on typing"
-    bug: "239979904"
+    bug: "335874198"
     is_fixed_read_only: true
 }
 
@@ -101,7 +101,7 @@
     name: "toolkit_frame_rate_function_enabling_read_only"
     namespace: "toolkit"
     description: "Feature flag to enable the functionality of the dVRR feature"
-    bug: "239979904"
+    bug: "335874198"
     is_fixed_read_only: true
 }
 
@@ -109,6 +109,6 @@
     name: "toolkit_frame_rate_view_enabling_read_only"
     namespace: "toolkit"
     description: "Feature flag to enable the functionality on views for the dVRR feature"
-    bug: "239979904"
+    bug: "335874198"
     is_fixed_read_only: true
 }
\ No newline at end of file
diff --git a/core/java/android/widget/flags/notification_widget_flags.aconfig b/core/java/android/widget/flags/notification_widget_flags.aconfig
index 95794f3..3a39631 100644
--- a/core/java/android/widget/flags/notification_widget_flags.aconfig
+++ b/core/java/android/widget/flags/notification_widget_flags.aconfig
@@ -37,3 +37,13 @@
     purpose: PURPOSE_BUGFIX
   }
 }
+
+flag {
+    name: "big_picture_style_discard_empty_icon_bitmap_drawables"
+    namespace: "systemui"
+    description: "BigPictureStyle: Ignore Icon BitmapDrawables without Bitmaps"
+    bug: "335878768"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/core/java/android/window/BackNavigationInfo.java b/core/java/android/window/BackNavigationInfo.java
index b1cf834..f24bc74 100644
--- a/core/java/android/window/BackNavigationInfo.java
+++ b/core/java/android/window/BackNavigationInfo.java
@@ -22,6 +22,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
+import android.graphics.Color;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -111,6 +112,8 @@
     @Nullable
     private final CustomAnimationInfo mCustomAnimationInfo;
 
+    private final int mLetterboxColor;
+
     /**
      * Create a new {@link BackNavigationInfo} instance.
      *
@@ -124,13 +127,15 @@
             @Nullable IOnBackInvokedCallback onBackInvokedCallback,
             boolean isPrepareRemoteAnimation,
             boolean isAnimationCallback,
-            @Nullable CustomAnimationInfo customAnimationInfo) {
+            @Nullable CustomAnimationInfo customAnimationInfo,
+            int letterboxColor) {
         mType = type;
         mOnBackNavigationDone = onBackNavigationDone;
         mOnBackInvokedCallback = onBackInvokedCallback;
         mPrepareRemoteAnimation = isPrepareRemoteAnimation;
         mAnimationCallback = isAnimationCallback;
         mCustomAnimationInfo = customAnimationInfo;
+        mLetterboxColor = letterboxColor;
     }
 
     private BackNavigationInfo(@NonNull Parcel in) {
@@ -140,6 +145,7 @@
         mPrepareRemoteAnimation = in.readBoolean();
         mAnimationCallback = in.readBoolean();
         mCustomAnimationInfo = in.readTypedObject(CustomAnimationInfo.CREATOR);
+        mLetterboxColor = in.readInt();
     }
 
     /** @hide */
@@ -151,6 +157,7 @@
         dest.writeBoolean(mPrepareRemoteAnimation);
         dest.writeBoolean(mAnimationCallback);
         dest.writeTypedObject(mCustomAnimationInfo, flags);
+        dest.writeInt(mLetterboxColor);
     }
 
     /**
@@ -193,6 +200,13 @@
     }
 
     /**
+     * @return Letterbox color
+     * @hide
+     */
+    public int getLetterboxColor() {
+        return mLetterboxColor;
+    }
+    /**
      * Callback to be called when the back preview is finished in order to notify the server that
      * it can clean up the resources created for the animation.
      * @hide
@@ -387,6 +401,8 @@
         private CustomAnimationInfo mCustomAnimationInfo;
         private boolean mAnimationCallback = false;
 
+        private int mLetterboxColor = Color.TRANSPARENT;
+
         /**
          * @see BackNavigationInfo#getType()
          */
@@ -454,6 +470,14 @@
         }
 
         /**
+         * @param color Non-transparent if there contain letterbox color.
+         */
+        public Builder setLetterboxColor(int color) {
+            mLetterboxColor = color;
+            return this;
+        }
+
+        /**
          * Builds and returns an instance of {@link BackNavigationInfo}
          */
         public BackNavigationInfo build() {
@@ -461,7 +485,8 @@
                     mOnBackInvokedCallback,
                     mPrepareRemoteAnimation,
                     mAnimationCallback,
-                    mCustomAnimationInfo);
+                    mCustomAnimationInfo,
+                    mLetterboxColor);
         }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java b/core/java/android/window/BackTouchTracker.java
similarity index 74%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
rename to core/java/android/window/BackTouchTracker.java
index 8f04f12..eb23af2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
+++ b/core/java/android/window/BackTouchTracker.java
@@ -14,22 +14,21 @@
  * limitations under the License.
  */
 
-package com.android.wm.shell.back;
+package android.window;
 
 import android.annotation.FloatRange;
 import android.os.SystemProperties;
 import android.util.MathUtils;
 import android.view.MotionEvent;
 import android.view.RemoteAnimationTarget;
-import android.window.BackEvent;
-import android.window.BackMotionEvent;
 
 import java.io.PrintWriter;
 
 /**
  * Helper class to record the touch location for gesture and generate back events.
+ * @hide
  */
-class TouchTracker {
+public class BackTouchTracker {
     private static final String PREDICTIVE_BACK_LINEAR_DISTANCE_PROP =
             "persist.wm.debug.predictive_back_linear_distance";
     private static final int LINEAR_DISTANCE = SystemProperties
@@ -53,9 +52,13 @@
     private float mLatestVelocityY;
     private float mStartThresholdX;
     private int mSwipeEdge;
+    private boolean mShouldUpdateStartLocation = false;
     private TouchTrackerState mState = TouchTrackerState.INITIAL;
 
-    void update(float touchX, float touchY, float velocityX, float velocityY) {
+    /**
+     * Updates the tracker with a new motion event.
+     */
+    public void update(float touchX, float touchY, float velocityX, float velocityY) {
         /**
          * If back was previously cancelled but the user has started swiping in the forward
          * direction again, restart back.
@@ -74,34 +77,52 @@
         mLatestVelocityY = velocityY;
     }
 
-    void setTriggerBack(boolean triggerBack) {
+    /** Sets whether the back gesture is past the trigger threshold. */
+    public void setTriggerBack(boolean triggerBack) {
         if (mTriggerBack != triggerBack && !triggerBack) {
             mStartThresholdX = mLatestTouchX;
         }
         mTriggerBack = triggerBack;
     }
 
-    boolean getTriggerBack() {
+    /** Gets whether the back gesture is past the trigger threshold. */
+    public boolean getTriggerBack() {
         return mTriggerBack;
     }
 
-    void setState(TouchTrackerState state) {
+
+    /** Returns if the start location should be updated. */
+    public boolean shouldUpdateStartLocation() {
+        return mShouldUpdateStartLocation;
+    }
+
+    /** Sets if the start location should be updated. */
+    public void setShouldUpdateStartLocation(boolean shouldUpdate) {
+        mShouldUpdateStartLocation = shouldUpdate;
+    }
+
+    /** Sets the state of the touch tracker. */
+    public void setState(TouchTrackerState state) {
         mState = state;
     }
 
-    boolean isInInitialState() {
+    /** Returns if the tracker is in initial state. */
+    public boolean isInInitialState() {
         return mState == TouchTrackerState.INITIAL;
     }
 
-    boolean isActive() {
+    /** Returns if a back gesture is active. */
+    public boolean isActive() {
         return mState == TouchTrackerState.ACTIVE;
     }
 
-    boolean isFinished() {
+    /** Returns if a back gesture has been finished. */
+    public boolean isFinished() {
         return mState == TouchTrackerState.FINISHED;
     }
 
-    void setGestureStartLocation(float touchX, float touchY, int swipeEdge) {
+    /** Sets the start location of the back gesture. */
+    public void setGestureStartLocation(float touchX, float touchY, int swipeEdge) {
         mInitTouchX = touchX;
         mInitTouchY = touchY;
         mLatestTouchX = touchX;
@@ -110,25 +131,27 @@
         mStartThresholdX = mInitTouchX;
     }
 
-    /** Update the start location used to compute the progress
-     * to the latest touch location.
-     */
-    void updateStartLocation() {
+    /** Update the start location used to compute the progress to the latest touch location. */
+    public void updateStartLocation() {
         mInitTouchX = mLatestTouchX;
         mInitTouchY = mLatestTouchY;
         mStartThresholdX = mInitTouchX;
+        mShouldUpdateStartLocation = false;
     }
 
-    void reset() {
+    /** Resets the tracker. */
+    public void reset() {
         mInitTouchX = 0;
         mInitTouchY = 0;
         mStartThresholdX = 0;
         mTriggerBack = false;
         mState = TouchTrackerState.INITIAL;
         mSwipeEdge = BackEvent.EDGE_LEFT;
+        mShouldUpdateStartLocation = false;
     }
 
-    BackMotionEvent createStartEvent(RemoteAnimationTarget target) {
+    /** Creates a start {@link BackMotionEvent}. */
+    public BackMotionEvent createStartEvent(RemoteAnimationTarget target) {
         return new BackMotionEvent(
                 /* touchX = */ mInitTouchX,
                 /* touchY = */ mInitTouchY,
@@ -140,7 +163,8 @@
                 /* departingAnimationTarget = */ target);
     }
 
-    BackMotionEvent createProgressEvent() {
+    /** Creates a progress {@link BackMotionEvent}. */
+    public BackMotionEvent createProgressEvent() {
         float progress = getProgress(mLatestTouchX);
         return createProgressEvent(progress);
     }
@@ -152,7 +176,7 @@
      * @return progress value
      */
     @FloatRange(from = 0.0, to = 1.0)
-    float getProgress(float touchX) {
+    public float getProgress(float touchX) {
         // If back is committed, progress is the distance between the last and first touch
         // point, divided by the max drag distance. Otherwise, it's the distance between
         // the last touch point and the starting threshold, divided by max drag distance.
@@ -200,11 +224,20 @@
      * Maximum distance in pixels.
      * Progress is considered to be completed (1f) when this limit is exceeded.
      */
-    float getMaxDistance() {
+    public float getMaxDistance() {
         return mMaxDistance;
     }
 
-    BackMotionEvent createProgressEvent(float progress) {
+    public float getLinearDistance() {
+        return mLinearDistance;
+    }
+
+    public float getNonLinearFactor() {
+        return mNonLinearFactor;
+    }
+
+    /** Creates a progress {@link BackMotionEvent} for the given progress. */
+    public BackMotionEvent createProgressEvent(float progress) {
         return new BackMotionEvent(
                 /* touchX = */ mLatestTouchX,
                 /* touchY = */ mLatestTouchY,
@@ -216,6 +249,7 @@
                 /* departingAnimationTarget = */ null);
     }
 
+    /** Sets the thresholds for computing progress. */
     public void setProgressThresholds(float linearDistance, float maxDistance,
             float nonLinearFactor) {
         if (LINEAR_DISTANCE >= 0) {
@@ -227,13 +261,14 @@
         mNonLinearFactor = nonLinearFactor;
     }
 
-    void dump(PrintWriter pw, String prefix) {
-        pw.println(prefix + "TouchTracker state:");
+    /** Dumps debugging info. */
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + "BackTouchTracker state:");
         pw.println(prefix + "  mState=" + mState);
         pw.println(prefix + "  mTriggerBack=" + mTriggerBack);
     }
 
-    enum TouchTrackerState {
+    public enum TouchTrackerState {
         INITIAL, ACTIVE, FINISHED
     }
 
diff --git a/core/java/android/window/IOnBackInvokedCallback.aidl b/core/java/android/window/IOnBackInvokedCallback.aidl
index 159c0e8..e07d4a9 100644
--- a/core/java/android/window/IOnBackInvokedCallback.aidl
+++ b/core/java/android/window/IOnBackInvokedCallback.aidl
@@ -56,4 +56,9 @@
      * Wraps {@link OnBackInvokedCallback#onBackInvoked()}.
      */
     void onBackInvoked();
+
+    /**
+     * Sets whether the back gesture is past the trigger threshold.
+     */
+    void setTriggerBack(in boolean triggerBack);
 }
diff --git a/core/java/android/window/ImeOnBackInvokedDispatcher.java b/core/java/android/window/ImeOnBackInvokedDispatcher.java
index da1993d..ee6ba24 100644
--- a/core/java/android/window/ImeOnBackInvokedDispatcher.java
+++ b/core/java/android/window/ImeOnBackInvokedDispatcher.java
@@ -48,10 +48,17 @@
     static final String RESULT_KEY_PRIORITY = "priority";
     static final int RESULT_CODE_REGISTER = 0;
     static final int RESULT_CODE_UNREGISTER = 1;
+    static final int RESULT_CODE_START_DISPATCHING = 2;
+    static final int RESULT_CODE_STOP_DISPATCHING = 3;
     @NonNull
     private final ResultReceiver mResultReceiver;
     @NonNull
     private final BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
+    @NonNull
+    private final BackTouchTracker mTouchTracker = new BackTouchTracker();
+    // The handler to run callbacks on. This should be on the same thread
+    // the ViewRootImpl holding IME's WindowOnBackInvokedDispatcher is created on.
+    private Handler mHandler;
 
     public ImeOnBackInvokedDispatcher(Handler handler) {
         mResultReceiver = new ResultReceiver(handler) {
@@ -78,6 +85,10 @@
         mResultReceiver = in.readTypedObject(ResultReceiver.CREATOR);
     }
 
+    void setHandler(@NonNull Handler handler) {
+        mHandler = handler;
+    }
+
     @Override
     public void registerOnBackInvokedCallback(
             @OnBackInvokedDispatcher.Priority int priority,
@@ -89,8 +100,13 @@
         // the app process, which may treat the IME callback as weakly referenced. This will not
         // cause a memory leak because the app side already clears the reference correctly.
         final IOnBackInvokedCallback iCallback =
-                new WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper(
-                        callback, mProgressAnimator, false /* useWeakRef */);
+                new ImeOnBackInvokedCallbackWrapper(
+                        callback,
+                        mTouchTracker,
+                        mProgressAnimator,
+                        this,
+                        mHandler != null ? mHandler : Handler.getMain(),
+                        false /* useWeakRef */);
         bundle.putBinder(RESULT_KEY_CALLBACK, iCallback.asBinder());
         bundle.putInt(RESULT_KEY_PRIORITY, priority);
         bundle.putInt(RESULT_KEY_ID, callback.hashCode());
@@ -115,6 +131,12 @@
         dest.writeTypedObject(mResultReceiver, flags);
     }
 
+    /** Sets the progress thresholds for touch tracking */
+    public void setProgressThresholds(float linearDistance, float maxDistance,
+            float nonLinearFactor) {
+        mTouchTracker.setProgressThresholds(linearDistance, maxDistance, nonLinearFactor);
+    }
+
     @NonNull
     public static final Parcelable.Creator<ImeOnBackInvokedDispatcher> CREATOR =
             new Parcelable.Creator<ImeOnBackInvokedDispatcher>() {
@@ -131,15 +153,20 @@
     private void receive(
             int resultCode, Bundle resultData,
             @NonNull WindowOnBackInvokedDispatcher receivingDispatcher) {
-        final int callbackId = resultData.getInt(RESULT_KEY_ID);
         if (resultCode == RESULT_CODE_REGISTER) {
+            final int callbackId = resultData.getInt(RESULT_KEY_ID);
             int priority = resultData.getInt(RESULT_KEY_PRIORITY);
             final IOnBackInvokedCallback callback = IOnBackInvokedCallback.Stub.asInterface(
                     resultData.getBinder(RESULT_KEY_CALLBACK));
             registerReceivedCallback(
                     callback, priority, callbackId, receivingDispatcher);
         } else if (resultCode == RESULT_CODE_UNREGISTER) {
+            final int callbackId = resultData.getInt(RESULT_KEY_ID);
             unregisterReceivedCallback(callbackId, receivingDispatcher);
+        } else if (resultCode == RESULT_CODE_START_DISPATCHING) {
+            receiveStartDispatching(receivingDispatcher);
+        } else if (resultCode == RESULT_CODE_STOP_DISPATCHING) {
+            receiveStopDispatching(receivingDispatcher);
         }
     }
 
@@ -181,6 +208,63 @@
         mImeCallbacks.remove(callback);
     }
 
+    static class ImeOnBackInvokedCallbackWrapper extends
+            WindowOnBackInvokedDispatcher.OnBackInvokedCallbackWrapper {
+        @NonNull
+        private final ImeOnBackInvokedDispatcher mDispatcher;
+
+        ImeOnBackInvokedCallbackWrapper(
+                @NonNull OnBackInvokedCallback callback,
+                @NonNull BackTouchTracker touchTracker,
+                @NonNull BackProgressAnimator progressAnimator,
+                @NonNull ImeOnBackInvokedDispatcher dispatcher,
+                @NonNull Handler handler,
+                boolean useWeakRef) {
+            super(callback, touchTracker, progressAnimator, handler, useWeakRef);
+            mDispatcher = dispatcher;
+        }
+
+        @Override
+        public void onBackStarted(BackMotionEvent backEvent) {
+            super.onBackStarted(backEvent);
+            mDispatcher.sendStartDispatching();
+        }
+
+        @Override
+        public void onBackCancelled() {
+            super.onBackCancelled();
+            mDispatcher.sendStopDispatching();
+        }
+
+        @Override
+        public void onBackInvoked() throws RemoteException {
+            super.onBackInvoked();
+            mDispatcher.sendStopDispatching();
+        }
+    }
+
+    /** Notifies the app process that we've stopped dispatching to an IME callback */
+    private void sendStopDispatching() {
+        mResultReceiver.send(RESULT_CODE_STOP_DISPATCHING, null /* unused bundle */);
+    }
+
+    /** Notifies the app process that we've started dispatching to an IME callback */
+    private void sendStartDispatching() {
+        mResultReceiver.send(RESULT_CODE_START_DISPATCHING, null /* unused bundle */);
+    }
+
+    /** Receives IME's message that dispatching has started. */
+    private void receiveStopDispatching(
+            @NonNull WindowOnBackInvokedDispatcher receivingDispatcher) {
+        receivingDispatcher.onStopImeDispatching();
+    }
+
+    /** Receives IME's message that dispatching has stopped. */
+    private void receiveStartDispatching(
+            @NonNull WindowOnBackInvokedDispatcher receivingDispatcher) {
+        receivingDispatcher.onStartImeDispatching();
+    }
+
     /** Clears all registered callbacks on the instance. */
     public void clear() {
         // Unregister previously registered callbacks if there's any.
@@ -193,6 +277,7 @@
         // We should also stop running animations since all callbacks have been removed.
         // note: mSpring.skipToEnd(), in ProgressAnimator.reset(), requires the main handler.
         Handler.getMain().post(mProgressAnimator::reset);
+        sendStopDispatching();
     }
 
     static class ImeOnBackInvokedCallback implements OnBackInvokedCallback {
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index 47a4052..7f6678e 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -23,19 +23,24 @@
 import android.content.ContextWrapper;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.IWindow;
 import android.view.IWindowSession;
 import android.view.ImeBackAnimationController;
+import android.view.MotionEvent;
 
 import androidx.annotation.VisibleForTesting;
 
-
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 
 import java.io.PrintWriter;
@@ -63,6 +68,14 @@
 public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
     private IWindowSession mWindowSession;
     private IWindow mWindow;
+    @VisibleForTesting
+    public final BackTouchTracker mTouchTracker = new BackTouchTracker();
+    @VisibleForTesting
+    public final BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
+    // The handler to run callbacks on.
+    // This should be on the same thread the ViewRootImpl holding this instance is created on.
+    @NonNull
+    private final Handler mHandler;
     private static final String TAG = "WindowOnBackDispatcher";
     private static final boolean ENABLE_PREDICTIVE_BACK = SystemProperties
             .getInt("persist.wm.debug.predictive_back", 1) != 0;
@@ -86,11 +99,35 @@
     @GuardedBy("mLock")
     public final TreeMap<Integer, ArrayList<OnBackInvokedCallback>>
             mOnBackInvokedCallbacks = new TreeMap<>();
+
     private Checker mChecker;
     private final Object mLock = new Object();
+    // The threshold for back swipe full progress.
+    private float mBackSwipeLinearThreshold;
+    private float mNonLinearProgressFactor;
+    private boolean mImeDispatchingActive;
 
-    public WindowOnBackInvokedDispatcher(@NonNull Context context) {
+    public WindowOnBackInvokedDispatcher(@NonNull Context context, Looper looper) {
         mChecker = new Checker(context);
+        mHandler = new Handler(looper);
+    }
+
+    /** Updates the dispatcher state on a new {@link MotionEvent}. */
+    public void onMotionEvent(MotionEvent ev) {
+        if (!isDispatching() || ev == null || ev.getAction() != MotionEvent.ACTION_MOVE) {
+            return;
+        }
+        mTouchTracker.update(ev.getX(), ev.getY(), Float.NaN, Float.NaN);
+        if (mTouchTracker.shouldUpdateStartLocation()) {
+            // Reset the start location on the first event after starting back, so that
+            // the beginning of the animation feels smooth.
+            mTouchTracker.updateStartLocation();
+        }
+        if (!mProgressAnimator.isBackAnimationInProgress()) {
+            return;
+        }
+        final BackMotionEvent backEvent = mTouchTracker.createProgressEvent();
+        mProgressAnimator.onBackProgressed(backEvent);
     }
 
     /**
@@ -207,19 +244,7 @@
      */
     public boolean isDispatching() {
         synchronized (mLock) {
-            return mIsDispatching;
-        }
-    }
-
-    private void onStartDispatching() {
-        synchronized (mLock) {
-            mIsDispatching = true;
-        }
-    }
-
-    private void onStopDispatching() {
-        synchronized (mLock) {
-            mIsDispatching = false;
+            return mTouchTracker.isActive() || mImeDispatchingActive;
         }
     }
 
@@ -263,7 +288,7 @@
 
             // We should also stop running animations since all callbacks have been removed.
             // note: mSpring.skipToEnd(), in ProgressAnimator.reset(), requires the main handler.
-            Handler.getMain().post(mProgressAnimator::reset);
+            mHandler.post(mProgressAnimator::reset);
             mAllCallbacks.clear();
             mOnBackInvokedCallbacks.clear();
         }
@@ -284,8 +309,9 @@
                                 callback).getIOnBackInvokedCallback()
                                 : new OnBackInvokedCallbackWrapper(
                                         callback,
+                                        mTouchTracker,
                                         mProgressAnimator,
-                                        this);
+                                        mHandler);
                 callbackInfo = new OnBackInvokedCallbackInfo(
                         iCallback,
                         priority,
@@ -312,10 +338,6 @@
         return null;
     }
 
-    @NonNull
-    private final BackProgressAnimator mProgressAnimator = new BackProgressAnimator();
-    private boolean mIsDispatching = false;
-
     /**
      * The {@link Context} in ViewRootImp and Activity could be different, this will make sure it
      * could update the checker condition base on the real context when binding the proxy
@@ -323,6 +345,26 @@
      */
     public void updateContext(@NonNull Context context) {
         mChecker = new Checker(context);
+        // Set swipe threshold values.
+        Resources res = context.getResources();
+        mBackSwipeLinearThreshold =
+                res.getDimension(R.dimen.navigation_edge_action_progress_threshold);
+        TypedValue typedValue = new TypedValue();
+        res.getValue(R.dimen.back_progress_non_linear_factor, typedValue, true);
+        mNonLinearProgressFactor = typedValue.getFloat();
+        onConfigurationChanged(context.getResources().getConfiguration());
+    }
+
+    /** Updates the threshold values for computing progress. */
+    public void onConfigurationChanged(Configuration configuration) {
+        float maxDistance = configuration.windowConfiguration.getMaxBounds().width();
+        float linearDistance = Math.min(maxDistance, mBackSwipeLinearThreshold);
+        mTouchTracker.setProgressThresholds(
+                linearDistance, maxDistance, mNonLinearProgressFactor);
+        if (mImeDispatcher != null) {
+            mImeDispatcher.setProgressThresholds(
+                    linearDistance, maxDistance, mNonLinearProgressFactor);
+        }
     }
 
     /**
@@ -354,6 +396,24 @@
         }
     }
 
+    /**
+     * Called when we start dispatching to a callback registered from IME.
+     */
+    public void onStartImeDispatching() {
+        synchronized (mLock) {
+            mImeDispatchingActive = true;
+        }
+    }
+
+    /**
+     * Called when we stop dispatching to a callback registered from IME.
+     */
+    public void onStopImeDispatching() {
+        synchronized (mLock) {
+            mImeDispatchingActive = false;
+        }
+    }
+
     static class OnBackInvokedCallbackWrapper extends IOnBackInvokedCallback.Stub {
         static class CallbackRef {
             final WeakReference<OnBackInvokedCallback> mWeakRef;
@@ -376,83 +436,81 @@
             }
         }
         final CallbackRef mCallbackRef;
-        /**
-         * The dispatcher this callback is registered with.
-         * This can be null for callbacks on {@link ImeOnBackInvokedDispatcher} because they are
-         * forwarded and registered on the app's {@link WindowOnBackInvokedDispatcher}. */
-        @Nullable
-        private final WindowOnBackInvokedDispatcher mDispatcher;
         @NonNull
         private final BackProgressAnimator mProgressAnimator;
+        @NonNull
+        private final BackTouchTracker mTouchTracker;
+        @NonNull
+        private final Handler mHandler;
 
         OnBackInvokedCallbackWrapper(
                 @NonNull OnBackInvokedCallback callback,
+                @NonNull BackTouchTracker touchTracker,
                 @NonNull BackProgressAnimator progressAnimator,
-                WindowOnBackInvokedDispatcher dispatcher) {
+                @NonNull Handler handler) {
             mCallbackRef = new CallbackRef(callback, true /* useWeakRef */);
+            mTouchTracker = touchTracker;
             mProgressAnimator = progressAnimator;
-            mDispatcher = dispatcher;
+            mHandler = handler;
         }
 
         OnBackInvokedCallbackWrapper(
                 @NonNull OnBackInvokedCallback callback,
+                @NonNull BackTouchTracker touchTracker,
                 @NonNull BackProgressAnimator progressAnimator,
+                @NonNull Handler handler,
                 boolean useWeakRef) {
             mCallbackRef = new CallbackRef(callback, useWeakRef);
+            mTouchTracker = touchTracker;
             mProgressAnimator = progressAnimator;
-            mDispatcher = null;
+            mHandler = handler;
         }
 
         @Override
         public void onBackStarted(BackMotionEvent backEvent) {
-            Handler.getMain().post(() -> {
-                if (mDispatcher != null) {
-                    mDispatcher.onStartDispatching();
-                }
+            mHandler.post(() -> {
+                mTouchTracker.setState(BackTouchTracker.TouchTrackerState.ACTIVE);
+                mTouchTracker.setShouldUpdateStartLocation(true);
+                mTouchTracker.setGestureStartLocation(
+                        backEvent.getTouchX(), backEvent.getTouchY(), backEvent.getSwipeEdge());
+
                 final OnBackAnimationCallback callback = getBackAnimationCallback();
                 if (callback != null) {
-                    mProgressAnimator.reset();
                     callback.onBackStarted(new BackEvent(
-                            backEvent.getTouchX(), backEvent.getTouchY(),
-                            backEvent.getProgress(), backEvent.getSwipeEdge()));
+                            backEvent.getTouchX(),
+                            backEvent.getTouchY(),
+                            backEvent.getProgress(),
+                            backEvent.getSwipeEdge()));
                     mProgressAnimator.onBackStarted(backEvent, callback::onBackProgressed);
                 }
             });
         }
 
         @Override
-        public void onBackProgressed(BackMotionEvent backEvent) {
-            Handler.getMain().post(() -> {
-                final OnBackAnimationCallback callback = getBackAnimationCallback();
-                if (callback != null) {
-                    mProgressAnimator.onBackProgressed(backEvent);
-                }
-            });
-        }
+        public void onBackProgressed(BackMotionEvent backEvent) { }
 
         @Override
         public void onBackCancelled() {
-            Handler.getMain().post(() -> {
-                if (mDispatcher != null) {
-                    mDispatcher.onStopDispatching();
+            mHandler.post(() -> {
+                final OnBackAnimationCallback callback = getBackAnimationCallback();
+                if (callback == null) {
+                    mTouchTracker.reset();
+                    return;
                 }
                 mProgressAnimator.onBackCancelled(() -> {
-                    final OnBackAnimationCallback callback = getBackAnimationCallback();
-                    if (callback != null) {
-                        callback.onBackCancelled();
-                    }
+                    mTouchTracker.reset();
+                    callback.onBackCancelled();
                 });
             });
         }
 
         @Override
         public void onBackInvoked() throws RemoteException {
-            Handler.getMain().post(() -> {
-                if (mDispatcher != null) {
-                    mDispatcher.onStopDispatching();
-                }
+            mHandler.post(() -> {
+                mTouchTracker.reset();
                 boolean isInProgress = mProgressAnimator.isBackAnimationInProgress();
                 mProgressAnimator.reset();
+                // TODO(b/333957271): Re-introduce auto fling progress generation.
                 final OnBackInvokedCallback callback = mCallbackRef.get();
                 if (callback == null) {
                     Log.d(TAG, "Trying to call onBackInvoked() on a null callback reference.");
@@ -466,6 +524,11 @@
             });
         }
 
+        @Override
+        public void setTriggerBack(boolean triggerBack) throws RemoteException {
+            mTouchTracker.setTriggerBack(triggerBack);
+        }
+
         @Nullable
         private OnBackAnimationCallback getBackAnimationCallback() {
             OnBackInvokedCallback callback = mCallbackRef.get();
@@ -498,6 +561,11 @@
     public void setImeOnBackInvokedDispatcher(
             @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
         mImeDispatcher = imeDispatcher;
+        mImeDispatcher.setHandler(mHandler);
+        mImeDispatcher.setProgressThresholds(
+                mTouchTracker.getLinearDistance(),
+                mTouchTracker.getMaxDistance(),
+                mTouchTracker.getNonLinearFactor());
     }
 
     /** Returns true if a non-null {@link ImeOnBackInvokedDispatcher} has been set. **/
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index 87c47da..ee3e34f 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -152,4 +152,15 @@
   metadata {
       purpose: PURPOSE_BUGFIX
   }
+}
+
+flag {
+  name: "get_dimmer_on_closing"
+  namespace: "windowing_frontend"
+  description: "Change check for when to ignore a closing task's dim"
+  bug: "329233513"
+  is_fixed_read_only: true
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
 }
\ No newline at end of file
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 4f55441..d72207d 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -272,6 +272,7 @@
                 getOpenInWorkMessage(launchIntent, target.loadLabel(packageManagerForTargetUser)),
                 packageManagerForTargetUser);
 
+        ((Button) findViewById(R.id.button_open)).setText(getOpenInWorkButtonString(launchIntent));
 
         View telephonyInfo = findViewById(R.id.miniresolver_info_section);
 
@@ -310,7 +311,15 @@
                 packageManagerForTargetUser);
 
         View telephonyInfo = findViewById(R.id.miniresolver_info_section);
-        telephonyInfo.setVisibility(View.GONE);
+        telephonyInfo.setVisibility(View.VISIBLE);
+
+        if (isTextMessageIntent(launchIntent)) {
+            ((TextView) findViewById(R.id.miniresolver_info_section_text)).setText(
+                    R.string.miniresolver_private_space_messages_information);
+        } else {
+            ((TextView) findViewById(R.id.miniresolver_info_section_text)).setText(
+                    R.string.miniresolver_private_space_phone_information);
+        }
     }
 
     private void buildMiniResolver(ResolveInfo target, Intent launchIntent, int targetUserId,
@@ -334,7 +343,6 @@
         ((Button) findViewById(R.id.use_same_profile_browser)).setText(R.string.cancel);
         findViewById(R.id.use_same_profile_browser).setOnClickListener(v -> finish());
 
-        ((Button) findViewById(R.id.button_open)).setText(getOpenInWorkButtonString(launchIntent));
         findViewById(R.id.button_open).setOnClickListener(v -> {
             startActivityAsCaller(
                     launchIntent,
diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java
index 6ff546f..ded142c 100644
--- a/core/java/com/android/internal/compat/ChangeReporter.java
+++ b/core/java/com/android/internal/compat/ChangeReporter.java
@@ -18,22 +18,24 @@
 
 import static android.text.TextUtils.formatSimple;
 
+import static java.util.Collections.EMPTY_SET;
+
 import android.annotation.IntDef;
 import android.util.Log;
 import android.util.Slog;
 
-import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.compat.flags.Flags;
 import com.android.internal.util.FrameworkStatsLog;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
 
 /**
  * A helper class to report changes to stats log.
@@ -42,6 +44,8 @@
  */
 public final class ChangeReporter {
     private static final String TAG = "CompatChangeReporter";
+    private static final Function<Integer, Set<ChangeReport>> NEW_CHANGE_REPORT_SET =
+            uid -> Collections.synchronizedSet(new HashSet<>());
     private int mSource;
 
     private static final class ChangeReport {
@@ -69,15 +73,14 @@
     }
 
     // Maps uid to a set of ChangeReports (that were reported for that uid).
-    @GuardedBy("mReportedChanges")
-    private final Map<Integer, Set<ChangeReport>> mReportedChanges;
+    private final ConcurrentHashMap<Integer, Set<ChangeReport>> mReportedChanges;
 
     // When true will of every time to debug (logcat).
     private boolean mDebugLogAll;
 
     public ChangeReporter(@Source int source) {
         mSource = source;
-        mReportedChanges =  new HashMap<>();
+        mReportedChanges =  new ConcurrentHashMap<>();
         mDebugLogAll = false;
     }
 
@@ -93,14 +96,15 @@
      *                        actually log. If the sdk version does not matter, should be true.
      */
     public void reportChange(int uid, long changeId, int state, boolean isLoggableBySdk) {
-        if (shouldWriteToStatsLog(uid, changeId, state)) {
+        boolean isAlreadyReported =
+                checkAndSetIsAlreadyReported(uid, new ChangeReport(changeId, state));
+        if (!isAlreadyReported) {
             FrameworkStatsLog.write(FrameworkStatsLog.APP_COMPATIBILITY_CHANGE_REPORTED, uid,
                     changeId, state, mSource);
         }
-        if (shouldWriteToDebug(uid, changeId, state, isLoggableBySdk)) {
+        if (shouldWriteToDebug(isAlreadyReported, state, isLoggableBySdk)) {
             debugLog(uid, changeId, state);
         }
-        markAsReported(uid, new ChangeReport(changeId, state));
     }
 
     /**
@@ -129,7 +133,6 @@
         mDebugLogAll = false;
     }
 
-
     /**
      * Returns whether the next report should be logged to FrameworkStatsLog.
      *
@@ -139,28 +142,26 @@
      * @return true if the report should be logged
      */
     @VisibleForTesting
-    public boolean shouldWriteToStatsLog(int uid, long changeId, int state) {
+    boolean shouldWriteToStatsLog(int uid, long changeId, int state) {
         return !isAlreadyReported(uid, new ChangeReport(changeId, state));
     }
 
     /**
      * Returns whether the next report should be logged to logcat.
      *
-     * @param uid             affected by the change
-     * @param changeId        the reported change id
-     * @param state           of the reported change - enabled/disabled/only logged
-     * @param isLoggableBySdk whether debug logging is allowed for this change based on target
-     *                        SDK version. This is combined with other logic to determine whether to
-     *                        actually log. If the sdk version does not matter, should be true.
+     * @param isAlreadyReported is the change already reported
+     * @param state             of the reported change - enabled/disabled/only logged
+     * @param isLoggableBySdk   whether debug logging is allowed for this change based on target SDK
+     *                          version. This is combined with other logic to determine whether to
+     *                          actually log. If the sdk version does not matter, should be true.
      * @return true if the report should be logged
      */
-    @VisibleForTesting
-    public boolean shouldWriteToDebug(
-            int uid, long changeId, int state, boolean isLoggableBySdk) {
+    private boolean shouldWriteToDebug(
+            boolean isAlreadyReported, int state, boolean isLoggableBySdk) {
         // If log all bit is on, always return true.
         if (mDebugLogAll) return true;
         // If the change has already been reported, do not write.
-        if (isAlreadyReported(uid, new ChangeReport(changeId, state))) return false;
+        if (isAlreadyReported) return false;
 
         // If the flag is turned off or the TAG's logging is forced to debug level with
         // `adb setprop log.tag.CompatChangeReporter=DEBUG`, write to debug since the above checks
@@ -178,33 +179,53 @@
      * @param uid         affected by the change
      * @param changeId    the reported change id
      * @param state       of the reported change - enabled/disabled/only logged
+     *
      * @return true if the report should be logged
      */
     @VisibleForTesting
-    public boolean shouldWriteToDebug(int uid, long changeId, int state) {
+    boolean shouldWriteToDebug(int uid, long changeId, int state) {
         return shouldWriteToDebug(uid, changeId, state, true);
     }
 
-    private boolean isAlreadyReported(int uid, ChangeReport report) {
-        synchronized (mReportedChanges) {
-            Set<ChangeReport> reportedChangesForUid = mReportedChanges.get(uid);
-            if (reportedChangesForUid == null) {
-                return false;
-            } else {
-                return reportedChangesForUid.contains(report);
-            }
+    /**
+     * Returns whether the next report should be logged to logcat.
+     *
+     * @param uid               affected by the change
+     * @param changeId          the reported change id
+     * @param state             of the reported change - enabled/disabled/only logged
+     * @param isLoggableBySdk   whether debug logging is allowed for this change based on target SDK
+     *                          version. This is combined with other logic to determine whether to
+     *                          actually log. If the sdk version does not matter, should be true.
+     * @return true if the report should be logged
+     */
+    @VisibleForTesting
+    boolean shouldWriteToDebug(int uid, long changeId, int state, boolean isLoggableBySdk) {
+        return shouldWriteToDebug(
+                isAlreadyReported(uid, new ChangeReport(changeId, state)), state, isLoggableBySdk);
+    }
+
+    /**
+     * Return if change has been reported. Also mark change as reported if not.
+     *
+     * @param uid affected by the change
+     * @param changeReport change reported to be checked and marked as reported.
+     *
+     * @return true if change has been reported, and vice versa.
+     */
+    private boolean checkAndSetIsAlreadyReported(int uid, ChangeReport changeReport) {
+        boolean isAlreadyReported = isAlreadyReported(uid, changeReport);
+        if (!isAlreadyReported) {
+            markAsReported(uid, changeReport);
         }
+        return isAlreadyReported;
+    }
+
+    private boolean isAlreadyReported(int uid, ChangeReport report) {
+        return mReportedChanges.getOrDefault(uid, EMPTY_SET).contains(report);
     }
 
     private void markAsReported(int uid, ChangeReport report) {
-        synchronized (mReportedChanges) {
-            Set<ChangeReport> reportedChangesForUid = mReportedChanges.get(uid);
-            if (reportedChangesForUid == null) {
-                mReportedChanges.put(uid, new HashSet<ChangeReport>());
-                reportedChangesForUid = mReportedChanges.get(uid);
-            }
-            reportedChangesForUid.add(report);
-        }
+        mReportedChanges.computeIfAbsent(uid, NEW_CHANGE_REPORT_SET).add(report);
     }
 
     /**
@@ -216,9 +237,7 @@
      * @param uid to reset
      */
     public void resetReportedChanges(int uid) {
-        synchronized (mReportedChanges) {
-            mReportedChanges.remove(uid);
-        }
+        mReportedChanges.remove(uid);
     }
 
     private void debugLog(int uid, long changeId, int state) {
@@ -229,7 +248,6 @@
         } else {
             Log.d(TAG, message);
         }
-
     }
 
     /**
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 5705b7e..7ac553c 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -48,8 +48,6 @@
 public abstract class PackageMonitor extends android.content.BroadcastReceiver {
     static final String TAG = "PackageMonitor";
 
-    final IntentFilter mPackageFilt;
-
     Context mRegisteredContext;
     Handler mRegisteredHandler;
     String[] mDisappearingPackages;
@@ -66,17 +64,32 @@
 
     private Executor mExecutor;
 
+    final boolean mSupportsPackageRestartQuery;
+
     @UnsupportedAppUsage
     public PackageMonitor() {
+        this(true);
+    }
+
+    /**
+     * The constructor of PackageMonitor whose parameters clearly indicate whether support
+     * querying package restart event.
+     */
+    public PackageMonitor(boolean supportsPackageRestartQuery) {
+        mSupportsPackageRestartQuery = supportsPackageRestartQuery;
+    }
+
+    private IntentFilter getPackageFilter() {
         final boolean isCore = UserHandle.isCore(android.os.Process.myUid());
 
-        mPackageFilt = new IntentFilter();
+        IntentFilter filter = new IntentFilter();
         // Settings app sends the broadcast
-        mPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
-        mPackageFilt.addDataScheme("package");
+        filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
+        filter.addDataScheme("package");
         if (isCore) {
-            mPackageFilt.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+            filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
         }
+        return filter;
     }
 
     @UnsupportedAppUsage
@@ -91,7 +104,6 @@
                 (thread == null) ? BackgroundThread.getHandler() : new Handler(thread));
     }
 
-
     /**
      * Register for notifications of package changes such as install, removal and other events.
      */
@@ -101,10 +113,13 @@
         }
         mRegisteredContext = context;
         mRegisteredHandler = Objects.requireNonNull(handler);
-        if (user != null) {
-            context.registerReceiverAsUser(this, user, mPackageFilt, null, mRegisteredHandler);
-        } else {
-            context.registerReceiver(this, mPackageFilt, null, mRegisteredHandler);
+        if (mSupportsPackageRestartQuery) {
+            final IntentFilter filter = getPackageFilter();
+            if (user != null) {
+                context.registerReceiverAsUser(this, user, filter, null, mRegisteredHandler);
+            } else {
+                context.registerReceiver(this, filter, null, mRegisteredHandler);
+            }
         }
         if (mPackageMonitorCallback == null) {
             PackageManager pm = mRegisteredContext.getPackageManager();
@@ -126,7 +141,9 @@
         if (mRegisteredContext == null) {
             throw new IllegalStateException("Not registered");
         }
-        mRegisteredContext.unregisterReceiver(this);
+        if (mSupportsPackageRestartQuery) {
+            mRegisteredContext.unregisterReceiver(this);
+        }
 
         PackageManager pm = mRegisteredContext.getPackageManager();
         if (pm != null && mPackageMonitorCallback != null) {
@@ -378,7 +395,7 @@
      * @param intent the intent that contains package related event information
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
-    public void doHandlePackageEvent(Intent intent) {
+    public final void doHandlePackageEvent(Intent intent) {
         mChangeUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
                 UserHandle.USER_NULL);
         if (mChangeUserId == UserHandle.USER_NULL) {
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index ab37252..f4315e3 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -521,6 +521,13 @@
         }
 
         ViewRootImpl viewRootImpl = getViewRootImpl();
+        if (viewRootImpl != null) {
+            viewRootImpl.getOnBackInvokedDispatcher().onMotionEvent(event);
+            // Intercept touch if back dispatching is active.
+            if (viewRootImpl.getOnBackInvokedDispatcher().isDispatching()) {
+                return true;
+            }
+        }
         if (viewRootImpl != null && mWearGestureInterceptionDetector != null) {
             boolean wasIntercepting = mWearGestureInterceptionDetector.isIntercepting();
             boolean intercepting = mWearGestureInterceptionDetector.onInterceptTouchEvent(event);
@@ -2125,6 +2132,11 @@
         super.onConfigurationChanged(newConfig);
 
         initializeElevation();
+
+        ViewRootImpl viewRootImpl = getViewRootImpl();
+        if (viewRootImpl != null) {
+            viewRootImpl.getOnBackInvokedDispatcher().onConfigurationChanged(newConfig);
+        }
     }
 
     @Override
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 52487fb..a091e19 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -37,6 +37,7 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -46,7 +47,9 @@
 import android.app.SearchManager;
 import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
 import android.compat.annotation.EnabledSince;
+import android.compat.annotation.Overridable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.Intent;
@@ -180,6 +183,15 @@
     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
     private static final long ENFORCE_EDGE_TO_EDGE = 309578419;
 
+    /**
+     * Override the layout in display cutout mode behavior. This will only apply if the edge to edge
+     * is not enforced.
+     */
+    @ChangeId
+    @Disabled
+    @Overridable
+    private static final long OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE = 332679525L;
+
     private static final int CUSTOM_TITLE_COMPATIBLE_FEATURES = DEFAULT_FEATURES |
             (1 << FEATURE_CUSTOM_TITLE) |
             (1 << FEATURE_CONTENT_TRANSITIONS) |
@@ -2475,6 +2487,11 @@
             getAttributes().privateFlags |= PRIVATE_FLAG_EDGE_TO_EDGE_ENFORCED;
             mDecorFitsSystemWindows = false;
         }
+        if (CompatChanges.isChangeEnabled(OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE)
+                && !a.getBoolean(R.styleable.Window_windowOptOutEdgeToEdgeEnforcement,
+                false /* defValue */)) {
+            getAttributes().privateFlags |= PRIVATE_FLAG_OVERRIDE_LAYOUT_IN_DISPLAY_CUTOUT_MODE;
+        }
 
         mIsFloating = a.getBoolean(R.styleable.Window_windowIsFloating, false);
         int flagsToUpdate = (FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR)
diff --git a/core/java/com/android/internal/policy/TransitionAnimation.java b/core/java/com/android/internal/policy/TransitionAnimation.java
index 9dec102..2f09a55 100644
--- a/core/java/com/android/internal/policy/TransitionAnimation.java
+++ b/core/java/com/android/internal/policy/TransitionAnimation.java
@@ -1340,35 +1340,39 @@
         final int pixelStride = plane.getPixelStride();
         final int rowStride = plane.getRowStride();
         final int sampling = 10;
-        final int[] borderLumas = new int[(width + height) * 2 / sampling];
+        final int[] histogram = new int[256];
 
         // Grab the top and bottom borders.
         int i = 0;
         for (int x = 0, size = width - sampling; x < size; x += sampling) {
-            borderLumas[i++] = getPixelLuminance(buffer, x, 0, pixelStride, rowStride);
-            borderLumas[i++] = getPixelLuminance(buffer, x, height - 1, pixelStride, rowStride);
+            final int topLm = getPixelLuminance(buffer, x, 0, pixelStride, rowStride);
+            final int bottomLm = getPixelLuminance(buffer, x, height - 1, pixelStride, rowStride);
+            histogram[topLm]++;
+            histogram[bottomLm]++;
         }
 
         // Grab the left and right borders.
         for (int y = 0, size = height - sampling; y < size; y += sampling) {
-            borderLumas[i++] = getPixelLuminance(buffer, 0, y, pixelStride, rowStride);
-            borderLumas[i++] = getPixelLuminance(buffer, width - 1, y, pixelStride, rowStride);
+            final int leftLm = getPixelLuminance(buffer, 0, y, pixelStride, rowStride);
+            final int rightLm = getPixelLuminance(buffer, width - 1, y, pixelStride, rowStride);
+            histogram[leftLm]++;
+            histogram[rightLm]++;
         }
 
         ir.close();
 
-        // Get "mode" by histogram.
-        final int[] histogram = new int[256];
-        int maxCount = 0;
-        int mostLuma = 0;
-        for (int luma : borderLumas) {
-            final int count = ++histogram[luma];
-            if (count > maxCount) {
-                maxCount = count;
-                mostLuma = luma;
+        // Find the median from histogram.
+        final int halfNum = (width + height) / sampling;
+        int sum = 0;
+        int medianLuminance = 0;
+        for (i = 0; i < histogram.length; i++) {
+            sum += histogram[i];
+            if (sum >= halfNum) {
+                medianLuminance = i;
+                break;
             }
         }
-        return mostLuma / 255f;
+        return medianLuminance / 255f;
     }
 
     /** Returns the luminance of the pixel in 0~255. */
diff --git a/core/java/com/android/internal/widget/BigPictureNotificationImageView.java b/core/java/com/android/internal/widget/BigPictureNotificationImageView.java
index 7e7aba2..1fff0c0 100644
--- a/core/java/com/android/internal/widget/BigPictureNotificationImageView.java
+++ b/core/java/com/android/internal/widget/BigPictureNotificationImageView.java
@@ -22,6 +22,7 @@
 import android.annotation.StyleRes;
 import android.app.ActivityManager;
 import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
@@ -29,6 +30,7 @@
 import android.util.Log;
 import android.widget.ImageView;
 import android.widget.RemoteViews;
+import android.widget.flags.Flags;
 
 import com.android.internal.R;
 
@@ -119,6 +121,22 @@
         return () -> setImageDrawable(drawable);
     }
 
+    @Override
+    public void setImageDrawable(@Nullable Drawable drawable) {
+        if (drawable instanceof BitmapDrawable bitmapDrawable) {
+            if (bitmapDrawable.getBitmap() == null) {
+                if (Flags.bigPictureStyleDiscardEmptyIconBitmapDrawables()) {
+                    Log.e(TAG, "discarding BitmapDrawable with null Bitmap (invalid image file?)");
+                    drawable = null;
+                } else {
+                    Log.e(TAG, "setting BitmapDrawable with null Bitmap (invalid image file?)");
+                }
+            }
+        }
+
+        super.setImageDrawable(drawable);
+    }
+
     private Drawable loadImage(Uri uri) {
         if (uri == null) return null;
         return LocalImageResolver.resolveImage(uri, mContext, mMaximumDrawableWidth,
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
index 18d5f6d..54b9a22 100644
--- a/core/java/com/android/internal/widget/LockscreenCredential.java
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -386,6 +386,11 @@
     }
 
     @Override
+    public void finalize() {
+        zeroize();
+    }
+
+    @Override
     public int hashCode() {
         // Effective Java — Always override hashCode when you override equals
         return Objects.hash(mType, Arrays.hashCode(mCredential), mHasInvalidChars);
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index d31baf3..e3a438d 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -1059,6 +1059,7 @@
 
             optional int32 uid = 1;
             repeated .android.app.ApplicationStartInfoProto app_start_info = 2;
+            optional bool monitoring_enabled = 3;
         }
         repeated User users = 2;
     }
diff --git a/core/proto/android/server/vibrator/vibratormanagerservice.proto b/core/proto/android/server/vibrator/vibratormanagerservice.proto
index 9151958..1d9b0db 100644
--- a/core/proto/android/server/vibrator/vibratormanagerservice.proto
+++ b/core/proto/android/server/vibrator/vibratormanagerservice.proto
@@ -116,7 +116,7 @@
     reserved 6; // prev int32 status
 
     // Also used by VibrationReported from frameworks/proto_logging/stats/atoms.proto.
-    // Next Tag: 26
+    // Next Tag: 29
     enum Status {
         UNKNOWN = 0;
         RUNNING = 1;
@@ -135,7 +135,6 @@
         IGNORED_ERROR_TOKEN= 14;
         IGNORED_APP_OPS = 15;
         IGNORED_BACKGROUND = 16;
-        IGNORED_UNKNOWN_VIBRATION = 17;
         IGNORED_UNSUPPORTED = 18;
         IGNORED_FOR_EXTERNAL = 19;
         IGNORED_FOR_HIGHER_IMPORTANCE = 20;
@@ -146,6 +145,8 @@
         IGNORED_SUPERSEDED = 25;
         IGNORED_FROM_VIRTUAL_DEVICE = 26;
         IGNORED_ON_WIRELESS_CHARGER = 27;
+        IGNORED_MISSING_PERMISSION = 28;
+        reserved 17; // prev IGNORED_UNKNOWN_VIBRATION
     }
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 567844c..e2106c5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -6200,7 +6200,7 @@
           @hide
           @removed -->
     <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|role" />
 
     <!-- Allows an application to know what content is playing and control its playback.
          <p>Not for use by third-party applications due to privacy of media consumption</p>  -->
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 8218ff1..dbf09ee 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -830,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Stel wagwoordreëls"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Beheer die lengte en die karakters wat in skermslotwagwoorde en -PIN\'e toegelaat word."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor pogings om skerm te ontsluit"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitor die aantal keer wat \'n verkeerde wagwoorde ingevoer is wanneer die skerm ontsluit word. Sluit die tablet of vee al die data uit as die wagwoord te veel keer verkeerd ingevoer word."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitor die aantal keer wat \'n verkeerde wagwoord ingevoer word wanneer die skerm ontsluit word. Sluit die tablet of vee al die data uit as die wagwoord te veel keer verkeerd ingevoer word."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitor die aantal verkeerde wagwoorde wat ingetik word wanneer die skerm ontsluit word, en sluit jou Android TV-toestel of vee al jou Android TV-toestel se data uit as te veel verkeerde wagwoorde ingetik word."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitor die aantal verkeerde wagwoorde wat ingevoer word wanneer die skerm ontsluit word, en sluit die inligtingvermaakstelsel of vee al die inligtingvermaakstelsel se data uit as te veel verkeerde wagwoorde ingevoer word."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Monitor die aantal keer wat \'n verkeerde wagwoorde ingevoer is wanneer die skerm ontsluit word. Sluit die foon of vee al die data uit as die wagwoord te veel keer verkeerd ingevoer word."</string>
@@ -843,7 +843,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Om die skerm te sluit"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Beheer hoe en wanneer die skerm sluit."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Om alle data uit te vee"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Vee die tablet se data uit sonder waarskuwing, deur \'n fabrieksterugstelling uit te voer."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Vee die tablet se data uit sonder waarskuwing, deur \'n fabriekterugstelling uit te voer."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Vee jou Android TV-toestel se data sonder waarskuwing uit deur \'n fabrieksterugstelling uit te voer."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Vee die inligtingvermaakstelsel se data sonder waarskuwing uit deur \'n fabriekterugstelling te doen."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Vee die foon se data uit sonder waarskuwing, deur \'n fabrieksterugstelling uit te voer."</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 5a79197..8a2fb4a 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -1899,8 +1899,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Traži PIN pre otkačinjanja"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Traži šablon za otključavanje pre otkačinjanja"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Traži lozinku pre otkačinjanja"</string>
-    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
-    <skip />
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"Instalirao je administrator.\nIdite u podešavanja da biste videli odobrene dozvole"</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Ažurirao je administrator"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisao je administrator"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Potvrdi"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 0ee66fc..484e6f0 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -2179,7 +2179,7 @@
     <string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"Obavještenja"</string>
     <string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Brze postavke"</string>
     <string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"Dijaloški okvir za napajanje"</string>
-    <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključavanje ekrana"</string>
+    <string name="accessibility_system_action_lock_screen_label" msgid="5484190691945563838">"Zaključani ekran"</string>
     <string name="accessibility_system_action_screenshot_label" msgid="3581566515062741676">"Snimak ekrana"</string>
     <string name="accessibility_system_action_headset_hook_label" msgid="8524691721287425468">"Kuka za slušalice"</string>
     <string name="accessibility_system_action_on_screen_a11y_shortcut_label" msgid="8488701469459210309">"Prečica za pristupačnost na ekranu"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 48ebcad..aafbb39 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -831,14 +831,14 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Definir les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Permet controlar la longitud i el nombre de caràcters permesos a les contrasenyes i als PIN del bloqueig de pantalla."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisar els intents de desbloqueig de la pantalla"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja la tauleta o n\'esborra totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
-    <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han introduït en intentar desbloquejar la pantalla i bloqueja el dispositiu Android TV o esborra totes les dades del dispositiu si s\'introdueixen massa contrasenyes incorrectes."</string>
-    <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el sistema d\'informació i entreteniment o n\'esborra totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el telèfon o esborra totes les dades del telèfon si s\'introdueixen massa contrasenyes incorrectes."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han escrit en intentar desbloquejar la pantalla i bloqueja la tauleta o n\'esborra totes les dades de l\'usuari si s\'escriuen massa contrasenyes incorrectes."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han introduït en intentar desbloquejar la pantalla i bloqueja el dispositiu Android TV o n\'esborra totes les dades de l\'usuari si s\'introdueixen massa contrasenyes incorrectes."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el sistema d\'informació i entreteniment o esborra totes les dades d\'aquest perfil si s\'introdueixen massa contrasenyes incorrectes."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Fa un seguiment del nombre de contrasenyes incorrectes que s\'han escrit en intentar desbloquejar la pantalla i bloqueja el telèfon o n\'esborra totes les dades de l\'usuari si s\'escriuen massa contrasenyes incorrectes."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja la tauleta o esborra\'n totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
+    <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el dispositiu Android TV o esborra\'n totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
+    <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el sistema d\'informació i entreteniment o esborra\'n totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el telèfon o esborra\'n totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja la tauleta o esborra totes les dades d\'aquest usuari si s\'introdueixen massa contrasenyes incorrectes."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el dispositiu Android TV o esborra totes les dades d\'aquest usuari si s\'introdueixen massa contrasenyes incorrectes."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el sistema d\'informació i entreteniment o esborra totes les dades d\'aquest perfil si s\'introdueixen massa contrasenyes incorrectes."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja el telèfon o esborra totes les dades d\'aquest usuari si s\'introdueixen massa contrasenyes incorrectes."</string>
     <string name="policylab_resetPassword" msgid="214556238645096520">"Canviar el bloqueig de pantalla"</string>
     <string name="policydesc_resetPassword" msgid="4626419138439341851">"Canvia el bloqueig de pantalla."</string>
     <string name="policylab_forceLock" msgid="7360335502968476434">"Bloquejar la pantalla"</string>
@@ -1899,8 +1899,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Sol·licita el PIN per deixar de fixar"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Sol·licita el patró de desbloqueig per deixar de fixar"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demana la contrasenya per deixar de fixar"</string>
-    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
-    <skip />
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"Instal·lat per l\'administrador.\nVes a la configuració per veure els permisos concedits."</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Actualitzat per l\'administrador"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Suprimit per l\'administrador"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"D\'acord"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index fef6fa6..f7b903f 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -832,7 +832,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Nastavit pravidla pro heslo"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Ovládání délky a znaků povolených v heslech a kódech PIN zámku obrazovky."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Sledovat pokusy o odemknutí obrazovky"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout tablet nebo vymazat z tabletu všechna data, pokud bylo zadáno příliš mnoho nesprávných hesel."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Monitoruje se počet nesprávných hesel zadaných při odemykání obrazovky, a pokud bylo zadáno příliš mnoho nesprávných hesel, tablet se uzamkne nebo se z něj vymažou všechna data."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Sledovat počet nesprávných hesel zadaných při odemykání obrazovky, a pokud jich bude zadáno příliš mnoho, uzamknout zařízení Android TV nebo z něj vymazat všechna data."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitorovat počet nesprávných hesel zadaných při odemykání obrazovky a uzamknout informační a zábavní systém nebo vymazat veškerá data v informačním a zábavním systému, pokud je zadáno příliš mnoho nesprávných hesel."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Sleduje počet nesprávných hesel zadaných při odemykání obrazovky a uzamkne telefon nebo vymaže z telefonu všechna data, pokud bylo zadáno příliš mnoho nesprávných hesel."</string>
@@ -845,7 +845,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Uzamknout obrazovku"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Určíte, jak a kdy se obrazovka uzamkne."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Mazat všechna data"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Bez upozornění smazat všechna data tabletu obnovením továrních dat."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Bez upozornění se smažou všechna data tabletu obnovením továrních dat."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Provést obnovení továrních dat a bez upozornění tím vymazat data v zařízení Android TV."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Bez upozornění se smažou všechna data informačního a zábavního systému obnovením továrních dat."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Bez upozornění se smažou všechna data telefonu obnovením továrních dat."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index ae1da16..0122a2c 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -830,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Passwortregeln festlegen"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Zulässige Länge und Zeichen für Passwörter für die Displaysperre festlegen"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Versuche zum Entsperren des Displays überwachen"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays überwachen und Tablet sperren oder alle Daten auf dem Tablet löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays überwachen und Tablet sperren oder alle Daten auf dem Tablet löschen, wenn zu häufig ein falsches Passwort eingegeben wird"</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Es wird überwacht, wie oft beim Versuch, den Bildschirm zu entsperren, ein falsches Passwort eingegeben wird. Wenn es zu viele Fehlversuche gibt, wird das Android TV-Gerät gesperrt oder alle Daten darauf werden gelöscht."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Displays erfassen und Infotainmentsystem sperren oder alle Daten des Infotainmentsystems löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Anzahl der falsch eingegebenen Passwörter beim Entsperren des Bildschirms überwachen und Telefon sperren oder alle Daten auf dem Telefon löschen, wenn zu häufig ein falsches Passwort eingegeben wird."</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 71b5903..15ac935 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -356,8 +356,7 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Take screenshot"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Can take a screenshot of the display."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Preview, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
-    <skip />
+    <string name="dream_accessibility_action_click" msgid="7392398629967797805">"dismiss"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"disable or modify status bar"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Allows the app to disable the status bar or add and remove system icons."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"be the status bar"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 25d6c18..78e4f32 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -356,8 +356,7 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎Take screenshot‎‏‎‎‏‎"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎Can take a screenshot of the display.‎‏‎‎‏‎"</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎Preview, ‎‏‎‎‏‏‎<xliff:g id="DREAM_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
-    <skip />
+    <string name="dream_accessibility_action_click" msgid="7392398629967797805">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‏‎dismiss‎‏‎‎‏‎"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎disable or modify status bar‎‏‎‎‏‎"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‎Allows the app to disable the status bar or add and remove system icons.‎‏‎‎‏‎"</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‎be the status bar‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 953bfbd..d524aac 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -844,7 +844,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Bloquear la pantalla"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Controla cómo y cuándo se bloquea la pantalla."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Borrar todos los datos"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Eliminar los datos de la tablet sin avisar y restablecer la configuración de fábrica"</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Borra los datos de la tablet sin avisar y restablece la configuración de fábrica."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Restablece la configuración de fábrica para borrar los datos del dispositivo Android TV sin previo aviso."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Permite borrar los datos del sistema de infoentretenimiento sin previo aviso mediante el restablecimiento de la configuración de fábrica."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Borra los datos del dispositivo sin avisar y restablece la configuración de fábrica."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index ba2c5e5..5f48741 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -831,7 +831,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Establecimiento de reglas de contraseña"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Controla la longitud y los caracteres permitidos en los PIN y en las contraseñas de bloqueo de pantalla."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisar los intentos de desbloqueo de pantalla"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea el tablet o elimina todos sus datos si se introducen demasiadas contraseñas incorrectas."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea la tablet o elimina todos sus datos si se introducen demasiadas contraseñas incorrectas."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Comprueba cuántas veces se han introducido contraseñas incorrectas para desbloquear la pantalla y, si te parece que han sido demasiadas, bloquea tu dispositivo Android TV o borra todos sus datos."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea el sistema de infoentretenimiento o borra todos sus datos si se introducen demasiadas contraseñas incorrectas."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Controla el número de contraseñas incorrectas introducidas al desbloquear la pantalla y bloquea el teléfono o elimina todos sus datos si se introducen demasiadas contraseñas incorrectas."</string>
@@ -844,7 +844,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Bloquear la pantalla"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Controla cómo y cuándo se bloquea la pantalla"</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Borrar todos los datos"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Borrar los datos del tablet sin avisar restableciendo el estado de fábrica"</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Borra los datos de la tablet sin avisar restableciendo el estado de fábrica"</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Restablece los datos de fábrica de tu dispositivo Android TV, eliminando sin previo aviso los datos que tuviera."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Borra los datos del sistema de infoentretenimiento sin avisar restableciendo el estado de fábrica."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Borra los datos del teléfono sin avisar restableciendo el estado de fábrica"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index b100016..1e50e92 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -843,7 +843,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Ekraani lukustamine"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Määrake, kuidas ja millal ekraan lukustub."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Kõikide andmete kustutamine"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Kustutage tahvelarvuti andmed hoiatamata, lähtestades arvuti tehaseandmetele."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Kustutab tahvelarvuti andmed hoiatamata, lähtestades arvuti tehaseandmetele."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Kustutatakse teie Android TV seadme andmed ilma hoiatamata, lähtestades seadme tehase andmetele."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Teabe ja meelelahutuse süsteemi andmete hoiatamata kustutamine tehase andmetele lähtestamise abil."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Kustutab telefoniandmed hoiatuseta, lähtestades telefoni tehaseseadetele."</string>
@@ -1898,8 +1898,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Enne vabastamist küsi PIN-koodi"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Enne vabastamist küsi avamismustrit"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Enne vabastamist küsi parooli"</string>
-    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
-    <skip />
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"Installis teie administraator.\nAntud õiguste vaatamiseks avage seaded"</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Administraator on seda värskendanud"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Administraator on selle kustutanud"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index aa87f24..2a21478 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1898,8 +1898,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Pyydä PIN ennen irrotusta"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Pyydä lukituksenpoistokuvio ennen irrotusta"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Pyydä salasana ennen irrotusta"</string>
-    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
-    <skip />
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"Järjestelmänvalvojan asentama.\nTarkista myönnetyt luvat asetuksista."</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Järjestelmänvalvoja päivitti tämän."</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Järjestelmänvalvoja poisti tämän."</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index f94ebac..a3d71d9 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1899,8 +1899,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Demander le code avant de retirer l\'épingle"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Demander le schéma de déverrouillage avant de retirer l\'épingle"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Demander le mot de passe avant de retirer l\'épingle"</string>
-    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
-    <skip />
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"Installé par votre administrateur.\nAllez dans les paramètres pour consulter les autorisations accordées."</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Mis à jour par votre administrateur"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f393074..9eb691f 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1898,8 +1898,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"अनपिन करने से पहले पिन के लिए पूछें"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"अनपिन करने से पहले लॉक खोलने के पैटर्न के लिए पूछें"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"अनपिन करने से पहले पासवर्ड के लिए पूछें"</string>
-    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
-    <skip />
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"इसे आपके एडमिन ने इंस्टॉल किया है.\nजिन अनुमतियों को मंज़ूरी मिली है उन्हें देखने के लिए, सेटिंग में जाएं"</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"आपके व्यवस्थापक ने अपडेट किया है"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"आपके व्यवस्थापक ने हटा दिया है"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"ठीक है"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 33cde13..84598ed 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -831,7 +831,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Postavi pravila zaporke"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Upravlja duljinom i znakovima koji su dopušteni u zaporkama i PIN-ovima zaključavanja zaslona."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Nadzor pokušaja otključavanja zaslona"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Nadziri broj netočnih zaporki unesenih pri otključavanju zaslona i zaključaj tabletno računalo ili izbriši sve podatke na njemu ako je uneseno previše netočnih zaporki."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Nadzire se broj netočnih zaporki unesenih pri otključavanju zaslona, a tablet se zaključava ili se s njega brišu svi podaci ako je uneseno previše netočnih zaporki."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava Android TV uređaj ili s njega briše sve podatke ako se unese previše netočnih zaporki."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Prati broj netočnih zaporki unesenih prilikom otključavanja zaslona i zaključava sustav za informiranje i zabavu ili briše sve njegove podatke ako se unese previše netočnih zaporki."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Nadzire broj netočno unesenih zaporki pri otključavanju zaslona i zaključava telefon ili briše sve podatke na telefonu ako je uneseno previše netočnih zaporki."</string>
@@ -844,7 +844,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Zaključavanje zaslona"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Upravlja se načinom i vremenom zaključavanja zaslona."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Brisanje svih podataka"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Vraćanjem u tvorničko stanje izbriši podatke tabletnog računala bez upozorenja."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Vraćanjem na tvorničke postavke brišu se podaci tableta bez upozorenja."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Podatke Android TV uređaja izbrišite bez upozorenja vraćanjem uređaja na tvorničke postavke."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Briše podatke sustava za informiranje i zabavu bez upozorenja vraćanjem na tvorničko stanje."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Vraćanjem na tvorničke postavke brišu se podaci s telefona bez upozorenja."</string>
@@ -1537,7 +1537,7 @@
     <string name="vpn_lockdown_config" msgid="8331697329868252169">"Promijenite mrežu ili postavke VPN-a"</string>
     <string name="upload_file" msgid="8651942222301634271">"Odaberite datoteku"</string>
     <string name="no_file_chosen" msgid="4146295695162318057">"Nema odabranih datoteka"</string>
-    <string name="reset" msgid="3865826612628171429">"Ponovo postavi"</string>
+    <string name="reset" msgid="3865826612628171429">"Poništi"</string>
     <string name="submit" msgid="862795280643405865">"Pošalji"</string>
     <string name="car_mode_disable_notification_title" msgid="8450693275833142896">"Pokrenuta je aplikacija za vožnju"</string>
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Dodirnite za zatvaranje aplikacije za vožnju."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index acf2266..d688035 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1898,8 +1898,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"PIN-kód kérése a kitűzés feloldásához"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Feloldási minta kérése a kitűzés feloldásához"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Jelszó kérése a rögzítés feloldásához"</string>
-    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
-    <skip />
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"A rendszergazda által telepítve.\nLépjen a beállításokhoz a megadott engedélyek megtekintéséhez."</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"A rendszergazda által frissítve"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"A rendszergazda által törölve"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index b304edc..2692d06 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -1898,8 +1898,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Biðja um PIN-númer til að losa"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Biðja um opnunarmynstur til að losa"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Biðja um aðgangsorð til að losa"</string>
-    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
-    <skip />
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"Sett upp af stjórnanda.\nFarðu í stillingar til að sjá heimildir"</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Kerfisstjóri uppfærði"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Kerfisstjóri eyddi"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Í lagi"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 00b79b6..2cc0590 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -844,7 +844,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"Bloccare lo schermo"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"Controlla come e quando si blocca lo schermo."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"Cancellare tutti i dati"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Cancella i dati del tablet senza preavviso eseguendo un ripristino dati di fabbrica."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"Cancella i dati del tablet senza preavviso eseguendo un ripristino dei dati di fabbrica."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"Consente di cancellare i dati del dispositivo Android TV senza preavviso eseguendo un ripristino dei dati di fabbrica."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"Cancella i dati del sistema di infotainment senza preavviso eseguendo un ripristino dei dati di fabbrica."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"Cancella i dati del telefono senza preavviso eseguendo un ripristino dei dati di fabbrica."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 5f6cd38..2ef91cd 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -843,7 +843,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"ចាក់សោ​អេក្រង់"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"គ្រប់គ្រងវិធី និង​ពេលវេលា​ចាក់សោ​អេក្រង់។"</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"លុប​ទិន្នន័យ​ទាំង​អស់"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"លុប​ទិន្នន័យ​កុំព្យូទ័រ​បន្ទះ​ដោយ​មិន​​ព្រមាន​ដោយ​អនុវត្ត​ការ​កំណត់​ទិន្នន័យ​ដូច​ចេញ​ពី​រោងចក្រ។"</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"លុប​ទិន្នន័យ​ថេប្លេត​ដោយ​គ្មានការព្រមាន​ដោយធ្វើការ​កំណត់​ទិន្នន័យ​ដូច​ចេញ​ពី​រោងចក្រ។"</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"លុប​ទិន្នន័យឧបករណ៍ Android TV របស់អ្នក​ដោយមិនមានការព្រមាន ដោយ​ធ្វើការកំណត់​ទិន្នន័យ​ដូច​ចេញ​ពី​រោងចក្រ។"</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"លុប​ទិន្នន័យ​របស់​ប្រព័ន្ធ​ព័ត៌មាន និងកម្សាន្ត​ដោយមិនមានការព្រមាន ដោយ​ធ្វើការកំណត់​ទិន្នន័យដូច​ចេញពី​រោងចក្រ។"</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"លុប​ទិន្នន័យ​ទូរសព្ទ​ដោយ​មិន​មានការព្រមានជាមុន ដោយ​អនុវត្ត​ការ​កំណត់​ទិន្នន័យ​ដូច​ចេញ​ពី​រោងចក្រ ។"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index ec92812..0d48bbb 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -830,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"ಪಾಸ್‌ವರ್ಡ್ ನಿಮಯಗಳನ್ನು ಹೊಂದಿಸಿ"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"ಪರದೆ ಲಾಕ್‌ನಲ್ಲಿನ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಪಿನ್‌ಗಳ ಅನುಮತಿಸಲಾದ ಅಕ್ಷರಗಳ ಪ್ರಮಾಣವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"ಪರದೆಯ ಅನ್‌ಲಾಕ್ ಪ್ರಯತ್ನಗಳನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ಪರದೆಯನ್ನು ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್‌ ಮಾಡಿದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ, ಮತ್ತು ಟ್ಯಾಬ್ಲೆಟ್‌ ಅನ್ನು ಲಾಕ್‌ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಟೈಪ್‌ ಮಾಡಿದ್ದರೆ ಟ್ಯಾಬ್ಲೆಟ್‌ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ಸ್ಕ್ರೀನ್ ಅನ್‌ಲಾಕ್‌ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್‌ ಮಾಡಿದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ, ಮತ್ತು ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಟೈಪ್‌ ಮಾಡಿದ್ದರೆ ಟ್ಯಾಬ್ಲೆಟ್‌ ಅನ್ನು ಲಾಕ್‌ ಮಾಡಿ ಅಥವಾ ಟ್ಯಾಬ್ಲೆಟ್‌ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ಪರದೆಯನ್ನು ಅನ್ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡುತ್ತದೆ ಮತ್ತು ನಿಮ್ಮ Android TV ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡುತ್ತದೆ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದರೆ ನಿಮ್ಮ ಎಲ್ಲಾ Android TV ಸಾಧನದ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕುತ್ತದೆ."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ಸ್ಕ್ರೀನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡುವಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ ಮತ್ತು ಇನ್‌ಫೋಟೈನ್‌ಮೆಂಟ್ ಸಿಸ್ಟಂ ಅನ್ನು ಲಾಕ್ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಟೈಪ್ ಮಾಡಿದ್ದರೆ ಇನ್‌ಫೋಟೈನ್‌ಮೆಂಟ್ ಸಿಸ್ಟಂನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿ."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ಪರದೆಯನ್ನು ಅನ್‌ಲಾಕ್‌ ಮಾಡಿದಾಗ ತಪ್ಪಾಗಿ ಟೈಪ್‌ ಮಾಡಿದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳ ಸಂಖ್ಯೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ, ಮತ್ತು ಫೋನ್‌‌ ಅನ್ನು ಲಾಕ್‌ ಮಾಡಿ ಅಥವಾ ಹಲವಾರು ತಪ್ಪಾದ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಟೈಪ್‌ ಮಾಡಿದ್ದರೆ ಫೋನ್‌‌ನ ಎಲ್ಲಾ ಡೇಟಾವನ್ನು ಅಳಿಸಿಹಾಕಿ."</string>
@@ -1898,8 +1898,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಿನ್‌ ಕೇಳು"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅನ್‌ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್ ಕೇಳು"</string>
-    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
-    <skip />
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿದ್ದಾರೆ.\nನೀಡಲಾದ ಅನುಮತಿಗಳನ್ನು ವೀಕ್ಷಿಸಲು ಸೆಟ್ಟಿಂಗ್‌ಗಳಿಗೆ ಹೋಗಿ"</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರಿಂದ ಅಪ್‌ಡೇಟ್ ಮಾಡಲ್ಪಟ್ಟಿದೆ"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ಅಳಿಸಿದ್ದಾರೆ"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"ಸರಿ"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 12adb17..1ffde6f 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -830,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"ຕັ້ງຄ່າກົດຂອງລະຫັດຜ່ານ"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"ຄວບຄຸມຄວາມຍາວ ແລະຕົວອັກສອນທີ່ອະ​ນຸ​ຍາດ​ໃຫ້​ຢູ່​ໃນລະ​ຫັດລັອກໜ້າຈໍ ແລະ PIN."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"ຕິດຕາມການພະຍາຍາມປົດລັອກໜ້າຈໍ"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ຕິດຕາມເບິ່ງຈຳນວນການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງ ໃນເວລາປົດລັອກໜ້າຈໍ ແລະລັອກແທັບເລັດ ຫຼືລຶບຂໍ້ມູນທັງໝົດຂອງແທັບເລັດ ຖ້າມີການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງຫຼາຍເທື່ອເກີນໄປ."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ຕິດຕາມເບິ່ງຈຳນວນການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງ ໃນເວລາປົດລັອກໜ້າຈໍ ແລະ ລັອກແທັບເລັດ ຫຼື ລຶບຂໍ້ມູນທັງໝົດຂອງແທັບເລັດ ຖ້າມີການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງຫຼາຍເທື່ອເກີນໄປ."</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ຕິດຕາມຈຳນວນລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງທີ່ພິມຕອນກຳລັງປົດລັອກໜ້າຈໍ ແລະ ລັອກອຸປະກອນ Android TV ຂອງທ່ານ ຫຼື ລຶບຂໍ້ມູນຂອງອຸປະກອນ Android TV ຂອງທ່ານຫາກພິມລະຫັດຜ່ານຜິດຫຼາຍເທື່ອເກີນໄປ."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ຕິດຕາມຈຳນວນການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງໃນເວລາປົດລັອກໜ້າຈໍ ແລະ ລັອກລະບົບສາລະບັນເທີງ ຫຼື ລຶບຂໍ້ມູນຂອງລະບົບສາລະບັນເທີງທັງໝົດຫາກມີການພິມລະຫັດຜ່ານທີ່ບໍ່ຖືກຕ້ອງຫຼາຍເກີນໄປ."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ຕິດຕາມເບິ່ງຈຳນວນການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ ໃນເວລາປົດລັອກໜ້າຈໍ ແລະລັອກໂທລະສັບ ຫຼືລຶບຂໍ້ມູນທັງໝົດຂອງໂປລະສັບ ຖ້າມີການພິມລະຫັດຜ່ານບໍ່ຖືກຕ້ອງຫຼາຍເທື່ອເກີນໄປ."</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 230e701..30e4eca 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -830,14 +830,14 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियमहरू मिलाउनुहोस्"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"स्क्रिन लक पासवर्ड र PIN हरूमा अनुमति दिइएको लम्बाइ र वर्णहरूको नियन्त्रण गर्नुहोस्।"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"स्क्रिन अनलक गर्न गरिएको प्रयासको अनुगमन गर्ने"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप भएको संख्या निरीक्षण गर्नुहोस् र यदि निकै धेरै गलत पासवर्डहरू टाइप भएका छन भने ट्याब्लेट लक गर्नुहोस् वा ट्याब्लेटका सबै डेटा मेट्नुहोस्।"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुराको रेकर्ड राख्नुहोस् र धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा ट्याबलेट लक गर्नुहोस् वा यसका सबै डेटा मेटाउनुहोस्।"</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप गरेको सङ्ख्या निरीक्षण गर्नुहोस्, र धेरै पटक गलत पासवर्डहरू टाइप गरिएको खण्डमा आफ्नो Android टिभी यन्त्र लक गर्नुहोस् वा डिभाइसमा भएको सम्पूर्ण डेटा मेटाउनुहोस्।"</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुरा निगरानी गर्नुहोस् र अत्यन्तै धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा यो इन्फोटेनमेन्ट प्रणाली लक गर्नुहोस् वा यस इन्फोटेनमेन्ट प्रणालीका सबै डेटा मेटाउनुहोस्।"</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप भएको छ हेर्नुहोस् र निकै धेरै पटक गलत पासवर्ड टाइप भएको भने फोन लक गर्नुहोस् वा फोनका सबै डेटा मेट्नुहोस्।"</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा ट्याब्लेट लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुराको रेकर्ड राख्नुहोस् र धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा ट्याबलेट लक गर्नुहोस् वा प्रयोगकर्ताका सबै डेटा मेटाउनुहोस्।"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप गरेको सङ्ख्या निरीक्षण गर्नुहोस्, र धेरै पटक गलत पासवर्डहरू टाइप गरिएको खण्डमा आफ्नो Android टिभी यन्त्र लक गर्नुहोस् वा यो प्रयोगकर्ताको सम्पूर्ण डेटा मेटाउनुहोस्।"</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुरा निगरानी गर्नुहोस् र अत्यन्तै धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा यो इन्फोटेनमेन्ट प्रणाली लक गर्नुहोस् वा यस प्रोफाइलका सबै डेटा मेटाउनुहोस्।"</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"स्क्रिन अनलक गर्दा गलत पासवर्ड टाइप संख्या अनुगमन गर्नुहोस्, र यदि निकै धेरै गलत पासवर्डहरू टाइप गरिएमा फोन लक गर्नुहोस् वा प्रयोगकर्ताको डेटा मेटाउनुहोस्।"</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"स्क्रिन अनलक गर्दा कति पटक गलत पासवर्ड टाइप गरिन्छ भन्ने कुराको रेकर्ड राख्नुहोस् र धेरै पटक गलत पासवर्ड टाइप गरिएका खण्डमा फोन लक गर्नुहोस् वा प्रयोगकर्ताका सबै डेटा मेटाउनुहोस्।"</string>
     <string name="policylab_resetPassword" msgid="214556238645096520">"स्क्रिन लक परिवर्तन गर्ने"</string>
     <string name="policydesc_resetPassword" msgid="4626419138439341851">"स्क्रिन लक परिवर्तन गर्नुहोस्।"</string>
     <string name="policylab_forceLock" msgid="7360335502968476434">"स्क्रिन लक गर्ने"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5de3287..f59d2ae 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -356,8 +356,7 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Screenshot maken"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"Kan een screenshot van het scherm maken."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Voorbeeld, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
-    <skip />
+    <string name="dream_accessibility_action_click" msgid="7392398629967797805">"sluiten"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"statusbalk uitzetten of wijzigen"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Hiermee kan de app de statusbalk uitzetten of systeemiconen toevoegen en verwijderen."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"de statusbalk zijn"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 6f186ff..9c41d73 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -830,7 +830,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"ପାସ୍‌ୱର୍ଡ ନିୟମାବଳୀ ସେଟ୍ କରନ୍ତୁ"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"ଲକ୍‍ ସ୍କ୍ରୀନ୍‍ ପାସ୍‌ୱର୍ଡ ଓ PINରେ ଅନୁମୋଦିତ ଦୀର୍ଘତା ଓ ବର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"ସ୍କ୍ରିନ-ଅନଲକ କରିବା ଉଦ୍ୟମ ନୀରିକ୍ଷଣ କରିବା"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ସ୍କ୍ରୀନ୍‍ ଅନଲକ୍‍ କରିବାବେଳେ ଟାଇପ୍‍ କରିଥିବା ଭୁଲ ପାସୱର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରେ ଏବଂ ଟାବଲେଟ୍‍କୁ ଲକ୍‍ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ୍‍ କରାଯାଇଥାଏ, ତେବେ ଟାବଲେଟ୍‍ର ସମସ୍ତ ଡାଟା ଲିଭାଇଦିଏ।"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"ସ୍କ୍ରିନ ଅନଲକ କରିବା ସମୟରେ ଟାଇପ ହୋଇଥିବା ଭୁଲ ପାସୱାର୍ଡ ସଂଖ୍ୟା ମନିଟର କରେ ଏବଂ ଟାବଲେଟକୁ ଲକ କରିଦିଏ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସୱର୍ଡ ଟାଇପ କରାଯାଇଥାଏ, ତେବେ ଟାବଲେଟର ସବୁ ଡାଟା ଖାଲି ହୋଇଯାଏ।"</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"ସ୍କ୍ରିନ୍ ଅନ୍‌ଲକ୍ କରିବା ସମୟରେ ଟାଇପ୍ କରାଯାଇଥିବା ଭୁଲ ପାସ୍‌ୱାର୍ଡଗୁଡ଼ିକର ସଂଖ୍ୟାକୁ ନିରୀକ୍ଷଣ କରନ୍ତୁ ଏବଂ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌କୁ ଲକ୍ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକ ଭୁଲ ପାସ୍‌ୱାର୍ଡ ଟାଇପ୍ କରାଯାଇଥାଏ, ତେବେ ଆପଣଙ୍କ Android TV ଡିଭାଇସ୍‌ର ସମସ୍ତ ଡାଟା ଲିଭାଇ ଦିଅନ୍ତୁ।"</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"ସ୍କ୍ରିନ ଅନଲକ କରିବା ସମୟରେ ଟାଇପ କରାଯାଇଥିବା ଭୁଲ ପାସୱାର୍ଡର ସଂଖ୍ୟାକୁ ମନିଟର କରନ୍ତୁ ଏବଂ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମକୁ ଲକ କରନ୍ତୁ କିମ୍ବା ଯଦି ଅନେକଗୁଡ଼ିଏ ଭୁଲ ପାସୱାର୍ଡ ଟାଇପ କରାଯାଇଥାଏ ତେବେ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମର ସମସ୍ତ ଡାଟା ଖାଲି କରନ୍ତୁ।"</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"ଫୋନ ଅନଲକ କରିବା ବେଳେ ଟାଇପ କରାଯାଇଥିବା ଭୁଲ ପାସୱାର୍ଡର ସଂଖ୍ୟାକୁ ନୀରିକ୍ଷଣ କରିବା ଏବଂ ଯଦି ଏକାଧିକ ଥର ଭୁଲ ପାସୱାର୍ଡ ଟାଇପ କରାଯାଇଥାଏ ତେବେ ଫୋନକୁ ଲକ କରିବା ବା ଫୋନର ସମସ୍ତ ଡାଟା ଇରେଜ କରିବା।"</string>
@@ -843,7 +843,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"ସ୍କ୍ରିନ୍ ଲକ୍‌ କରିବା"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"ସ୍କ୍ରିନ୍ କିପରି ଓ କେତେବେଳେ ଲକ୍‍ କରାଯିବ, ତାହା ନିୟନ୍ତ୍ରଣ କରେ।"</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"ସମସ୍ତ ଡାଟା ଖାଲି କରିବା"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ବିନା ଚେତାବନୀରେ ଫ୍ୟାକ୍ଟୋରୀ ସେଟିଙ୍ଗ କରାଇ ଟାବ୍‍ଲେଟ୍‍ର ଡାଟା ଲିଭାଇଥାଏ।"</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ଫେକ୍ଟୋରୀ ଡାଟା ରିସେଟ କରି ବିନା ଚେତାବନୀରେ ଟାବଲେଟର ଡାଟା ଖାଲି କରନ୍ତୁ।"</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"ଏକ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ୍ କରି ବିନା ଚେତାବନୀରେ ଆପଣଙ୍କର Android TV ଡିଭାଇସ୍‌ର ଡାଟା ଲିଭାନ୍ତୁ।"</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ଏକ ଫ୍ୟାକ୍ଟୋରୀ ଡାଟା ରିସେଟ କରି ବିନା ଚେତାବନୀରେ ଇନଫୋଟେନମେଣ୍ଟ ସିଷ୍ଟମର ଡାଟା ଖାଲି କରନ୍ତୁ।"</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ବିନା ଚେତାବନୀରେ ଫେକ୍ଟୋରୀ ଡାଟା ରିସେଟ କରି ଫୋନର ଡାଟା ଇରେଜ କରିବା।"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a6937d2..ab40341 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -832,7 +832,7 @@
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Określ reguły hasła"</string>
     <string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolowanie długości haseł blokady ekranu i kodów PIN oraz dozwolonych w nich znaków."</string>
     <string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorowanie prób odblokowania ekranu"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Przy odblokowywaniu ekranu monitoruj, ile razy wpisano nieprawidłowe hasło i blokuj tablet lub usuń z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy."</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="2388436408621909298">"Przy odblokowywaniu ekranu monitoruje, ile razy wpisano nieprawidłowe hasło i blokuje tablet lub usuwa z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy"</string>
     <string name="policydesc_watchLogin" product="tv" msgid="2140588224468517507">"Monitorowanie liczby nieudanych prób odblokowania ekranu za pomocą hasła oraz blokowanie urządzenia z Androidem TV lub kasowanie z niego wszystkich danych w razie wpisania błędnego hasła zbyt wiele razy."</string>
     <string name="policydesc_watchLogin" product="automotive" msgid="7011438994051251521">"Monitorowanie przypadków nieprawidłowego wpisania hasła podczas odblokowywania ekranu i blokowanie systemu multimedialno-rozrywkowego lub usuwanie z niego wszystkich danych przy zbyt dużej liczbie błędnych prób."</string>
     <string name="policydesc_watchLogin" product="default" msgid="4885030206253600299">"Przy odblokowywaniu ekranu monitoruje, ile razy wpisano nieprawidłowe hasło, i blokuje telefon lub usuwa z niego wszystkie dane, jeśli nieprawidłowe hasło podano zbyt wiele razy."</string>
@@ -1267,7 +1267,7 @@
     <string name="screen_compat_mode_scale" msgid="8627359598437527726">"Skala"</string>
     <string name="screen_compat_mode_show" msgid="5080361367584709857">"Zawsze pokazuj"</string>
     <string name="screen_compat_mode_hint" msgid="4032272159093750908">"Włącz ponownie, wybierając Ustawienia systemu &gt; Aplikacje &gt; Pobrane."</string>
-    <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje obecnie ustawionego rozmiaru wyświetlacza i może działać niestabilnie."</string>
+    <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> nie obsługuje obecnie ustawionego rozmiaru wyświetlanych elementów i może działać niestabilnie."</string>
     <string name="unsupported_display_size_show" msgid="980129850974919375">"Zawsze pokazuj"</string>
     <string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> została skompilowana pod niezgodną wersję systemu Android i może zachowywać się niezgodnie z oczekiwaniami. Sprawdź, czy jest dostępna zaktualizowana wersja aplikacji."</string>
     <string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"Zawsze pokazuj"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 4772ff8..4d61bdd 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -357,8 +357,7 @@
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"Fazer captura de ecrã"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"É possível tirar uma captura de ecrã."</string>
     <string name="dream_preview_title" msgid="5570751491996100804">"Pré-visualização, <xliff:g id="DREAM_NAME">%1$s</xliff:g>"</string>
-    <!-- no translation found for dream_accessibility_action_click (7392398629967797805) -->
-    <skip />
+    <string name="dream_accessibility_action_click" msgid="7392398629967797805">"ignorar"</string>
     <string name="permlab_statusBar" msgid="8798267849526214017">"desativar ou modificar barra de estado"</string>
     <string name="permdesc_statusBar" msgid="5809162768651019642">"Permite à app desativar a barra de estado ou adicionar e remover ícones do sistema."</string>
     <string name="permlab_statusBarService" msgid="2523421018081437981">"ser apresentada na barra de estado"</string>
@@ -838,7 +837,7 @@
     <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="2049038943004297474">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o tablet ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="tv" msgid="8965224107449407052">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o dispositivo Android TV ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string>
     <string name="policydesc_watchLogin_secondaryUser" product="automotive" msgid="7180857406058327941">"Monitorize o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloqueie o sistema de infoentretenimento ou apague todos os dados deste utilizador, se forem introduzidas demasiadas palavras-passe incorretas."</string>
-    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã e bloquear o telemóvel ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="9177645136475155924">"Monitorizar o número de palavras-passe incorretas introduzidas ao desbloquear o ecrã, e bloquear o telemóvel ou apagar todos os dados deste utilizador se forem introduzidas demasiadas palavras-passe incorretas."</string>
     <string name="policylab_resetPassword" msgid="214556238645096520">"Alterar o bloqueio de ecrã"</string>
     <string name="policydesc_resetPassword" msgid="4626419138439341851">"Altera o bloqueio de ecrã."</string>
     <string name="policylab_forceLock" msgid="7360335502968476434">"Bloquear o ecrã"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 6768e29..569eb35 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1899,8 +1899,7 @@
     <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Тражи PIN пре откачињања"</string>
     <string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Тражи шаблон за откључавање пре откачињања"</string>
     <string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Тражи лозинку пре откачињања"</string>
-    <!-- no translation found for package_installed_device_owner (8684974629306529138) -->
-    <skip />
+    <string name="package_installed_device_owner" msgid="8684974629306529138">"Инсталирао је администратор.\nИдите у подешавања да бисте видели одобрене дозволе"</string>
     <string name="package_updated_device_owner" msgid="7560272363805506941">"Ажурирао је администратор"</string>
     <string name="package_deleted_device_owner" msgid="2292335928930293023">"Избрисао је администратор"</string>
     <string name="confirm_battery_saver" msgid="5247976246208245754">"Потврди"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 1c65e61..eb1e453 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -843,7 +843,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"திரையைப் பூட்டுதல்"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"திரை எப்படி, எப்போது பூட்டப்படுகிறது என்பதைக் கட்டுப்படுத்தலாம்."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"எல்லா டேட்டாவையும் அழித்தல்"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ஆரம்பநிலைத் தரவு மீட்டமைப்பின் மூலம் எச்சரிக்கை வழங்காமல் டேப்லெட்டின் தரவை அழிக்கலாம்."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ஆரம்பநிலைத் தரவு மீட்டமைப்பின் மூலம் எச்சரிக்கை வழங்காமல் டேப்லெட்டின் தரவை அழிக்கும்."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"தரவின் ஆரம்பநிலைக்கு மீட்டமைப்பதன் மூலம் எச்சரிக்கை செய்யாமல் Android TVயின் தரவை அழிக்கும்."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"தரவின் ஆரம்பநிலை மீட்டமைப்பைச் செயல்படுத்துவதன் மூலம் எச்சரிக்கை எதுவுமின்றி இன்ஃபோடெயின்மென்ட் சிஸ்டமின் தரவை அழிக்கும்."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ஆரம்பநிலைத் தரவு மீட்டமைப்பின் மூலம் எச்சரிக்கை வழங்காமல் மொபைலின் தரவை அழிக்கலாம்."</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 423cf88..3c82307 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -843,7 +843,7 @@
     <string name="policylab_forceLock" msgid="7360335502968476434">"స్క్రీన్‌ను లాక్ చేయడానికి"</string>
     <string name="policydesc_forceLock" msgid="1008844760853899693">"స్క్రీన్‌ను ఎలా మరియు ఎప్పుడు లాక్ చేయాలనే దాన్ని నియంత్రిస్తుంది."</string>
     <string name="policylab_wipeData" msgid="1359485247727537311">"మొత్తం డేటాను ఎరేజ్ చేయడానికి"</string>
-    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"ఫ్యాక్టరీ డేటా రీసెట్‌ను అమలు చేయడం ద్వారా హెచ్చరించకుండానే టాబ్లెట్ డేటాను ఎరేజ్ చేయండి."</string>
+    <string name="policydesc_wipeData" product="tablet" msgid="7245372676261947507">"\'ఫ్యాక్టరీ డేటా రీసెట్‌\'ను అమలు చేయడం ద్వారా వార్నింగ్‌తో పని లేకుండా టాబ్లెట్ డేటాను ఎరేజ్ చేయండి."</string>
     <string name="policydesc_wipeData" product="tv" msgid="513862488950801261">"హెచ్చరించకుండానే మీ Android TV పరికరం డేటాను ఫ్యాక్టరీ డేటా రీసెట్ ద్వారా తొలగిస్తుంది."</string>
     <string name="policydesc_wipeData" product="automotive" msgid="660804547737323300">"ఫ్యాక్టరీ డేటా రీసెట్‌ను అమలు చేయడం ద్వారా, హెచ్చరిక లేకుండానే సమాచారంతో కూడిన వినోదం సిస్టమ్ డేటాను తొలగించి ఫ్యాక్టరీ రీసెట్ చేయబడుతుంది."</string>
     <string name="policydesc_wipeData" product="default" msgid="8036084184768379022">"ఫ్యాక్టరీ డేటా రీసెట్‌ను అమలు చేయడం ద్వారా హెచ్చరించకుండానే ఫోన్ డేటాను ఎరేజ్ చేస్తుంది."</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1a61870..b5256f8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2042,10 +2042,17 @@
          provider services. -->
     <string name="config_secondaryLocationTimeZoneProviderPackageName" translatable="false"></string>
 
+    <!-- Whether the telephony time zone detection feature is enabled. Setting this to false means
+         the feature cannot be used. Setting this to true means the feature will be enabled on the
+         device if FEATURE_TELEPHONY
+         (@see https: //developer.android.com/reference/android/content/pm/PackageManager#FEATURE_TELEPHONY)
+         is also supported. -->
+    <bool name="config_enableTelephonyTimeZoneDetection" translatable="false">true</bool>
+
     <!-- Whether the time zone detection logic supports fall back from geolocation suggestions to
          telephony suggestions temporarily in certain circumstances. Reduces time zone detection
          latency during some scenarios like air travel. Only useful when both geolocation and
-         telephony time zone detection are supported on a device.
+         telephony time zone detection are supported and enabled on a device.
          See com.android.server.timezonedetector.TimeZoneDetectorStrategy for more information. -->
     <bool name="config_supportTelephonyTimeZoneFallback" translatable="false">true</bool>
 
@@ -4824,7 +4831,7 @@
 
      See android.credentials.CredentialManager
     -->
-    <string name="config_defaultCredentialManagerAutofillService" translatable="false"></string>
+    <string name="config_defaultCredentialManagerAutofillService" translatable="false">com.android.credentialmanager/com.android.credentialmanager.autofill.CredentialAutofillService</string>
 
     <!-- The component name(s), flattened to a string, for the system's credential manager
       provider services. These services allow retrieving and storing credentials.
diff --git a/core/res/res/values/config_telephony.xml b/core/res/res/values/config_telephony.xml
index a248ede..cc02a7e 100644
--- a/core/res/res/values/config_telephony.xml
+++ b/core/res/res/values/config_telephony.xml
@@ -190,6 +190,13 @@
     <integer name="config_satellite_nb_iot_inactivity_timeout_millis">180000</integer>
     <java-symbol type="integer" name="config_satellite_nb_iot_inactivity_timeout_millis" />
 
+    <!-- The time duration in millis after which cellular scanning will be enabled and satellite
+         will move to IDLE state. This timeout duration is used for satellite with NB IOT radio
+         technologies in demo mode.
+         -->
+    <integer name="config_satellite_demo_mode_nb_iot_inactivity_timeout_millis">60000</integer>
+    <java-symbol type="integer" name="config_satellite_demo_mode_nb_iot_inactivity_timeout_millis" />
+
     <!-- The time duration in millis needed to switch the modem image from TN to NTN. -->
     <integer name="config_satellite_modem_image_switching_duration_millis">20000</integer>
     <java-symbol type="integer" name="config_satellite_modem_image_switching_duration_millis" />
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 4aa741d..52ce993 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -1043,4 +1043,10 @@
     <dimen name="handwriting_bounds_offset_top">40dp</dimen>
     <dimen name="handwriting_bounds_offset_right">10dp</dimen>
     <dimen name="handwriting_bounds_offset_bottom">40dp</dimen>
+
+    <!-- The threshold for full back swipe progress. -->
+    <dimen name="navigation_edge_action_progress_threshold">412dp</dimen>
+    <!-- The non-linear progress interval when the screen is wider than the
+        navigation_edge_action_progress_threshold. -->
+    <item name="back_progress_non_linear_factor" format="float" type="dimen">0.2</item>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e96240d..4ea97a5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -399,28 +399,37 @@
     <string name="cfTemplateRegisteredTime"><xliff:g id="bearer_service_code">{0}</xliff:g>: Not forwarded</string>
 
     <!-- Title of the cellular network security safety center source's status. -->
-    <string name="scCellularNetworkSecurityTitle">Cellular network security</string>
+    <string name="scCellularNetworkSecurityTitle">Mobile network security</string>
     <!-- Summary of the cellular network security safety center source's status. -->
-    <string name="scCellularNetworkSecuritySummary">Review settings</string>
+    <string name="scCellularNetworkSecuritySummary">Encryption, notifications for unencrypted networks</string>
     <!-- Link passed to safety center for the Learn More button on notifications -->
     <!-- DO NOT TRANSLATE -->
     <string name="scCellularNetworkSecurityLearnMore" translatable="false"></string>
     <!-- Title of the safety center issue and notification when the phone's identifier is shared over the network. -->
-    <string name="scIdentifierDisclosureIssueTitle">Device identifier accessed</string>
-    <!-- Summary of the safety center issue and notification when the phone's identifier is shared over the network. -->
-    <string name="scIdentifierDisclosureIssueSummary">A network on the <xliff:g id="disclosure_network">%4$s</xliff:g> connection recorded your device\'s unique identifier (IMSI) <xliff:g id="disclosure_count">%1$d</xliff:g> times in the period between <xliff:g id="disclosure_window_start_time">%2$tr</xliff:g> and <xliff:g id="disclosure_window_end_time">%3$tr</xliff:g>.</string>
+    <string name="scIdentifierDisclosureIssueTitle">Device ID accessed</string>
+    <!-- Summary of the safety center notification when the phone's identifier is shared over the network. -->
+    <string name="scIdentifierDisclosureIssueSummaryNotification">At <xliff:g id="disclosure_time">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="disclosure_network">%2$s</xliff:g> SIM</string>
+    <!-- Summary of the safety center detail card when the phone's identifier is shared over the network. -->
+    <string name="scIdentifierDisclosureIssueSummary">At <xliff:g id="disclosure_time">%1$s</xliff:g>, a nearby network recorded your device\'s unique ID (IMSI or IMEI) while using your <xliff:g id="disclosure_network">%2$s</xliff:g> SIM.\n\nThis means that your location, activity, or identity have been logged. This is common practice but may be an issue for people concerned about privacy.</string>
+
     <!-- Title of the safety center issue and notification when the phone restores an encrypted connection to the network. -->
-    <string name="scNullCipherIssueEncryptedTitle">Encrypted connection to <xliff:g id="network_name">%1$s</xliff:g></string>
+    <string name="scNullCipherIssueEncryptedTitle">Connected to encrypted network <xliff:g id="network_name">%1$s</xliff:g></string>
     <!-- Summary of the safety center issue and notification when the phone restores an encrypted connection to the network. -->
-    <string name="scNullCipherIssueEncryptedSummary">You\'re now connected to a more secure cellular network.</string>
+    <string name="scNullCipherIssueEncryptedSummary"><xliff:g id="network_name">%1$s</xliff:g> SIM connection is more secure now</string>
     <!-- Title of the safety center issue and notification when a connected network is not using encryption. -->
-    <string name="scNullCipherIssueNonEncryptedTitle">Non-encrypted connection to <xliff:g id="network_name">%1$s</xliff:g></string>
-    <!-- Summary of the safety center issue and notification when a connected network is not using encryption.  -->
-    <string name="scNullCipherIssueNonEncryptedSummary">You\'re connected to a non-encrypted cellular network. Your calls, messages, and data are vulnerable to interception.</string>
+
+    <string name="scNullCipherIssueNonEncryptedTitle">Connected to unencrypted network</string>
+    <!-- Summary of the safety center notification when a connected network is not using encryption.  -->
+    <string name="scNullCipherIssueNonEncryptedSummaryNotification">Calls, messages, and data are currently more vulnerable while using your <xliff:g id="network_name">%1$s</xliff:g> SIM</string>
+    <!-- Summary of the safety center issue when a connected network is not using encryption.  -->
+    <string name="scNullCipherIssueNonEncryptedSummary">Calls, messages, and data are currently more vulnerable while using your <xliff:g id="network_name">%1$s</xliff:g> SIM.\n\nWhen your connection is encrypted again, you\'ll get another notification.</string>
+
     <!-- Label for the button that links to the cellular network security settings. -->
-    <string name="scNullCipherIssueActionSettings">Cellular security settings</string>
-    <!-- Label for the button that link to education resourcess about cellular network security settings. -->
+    <string name="scNullCipherIssueActionSettings">Mobile network security settings</string>
+    <!-- Label for the button that links to education resourcess about cellular network security settings. -->
     <string name="scNullCipherIssueActionLearnMore">Learn more</string>
+    <!-- Label for the button to acknowledge the user is connected to an encrypted network again in cellular network security settings. -->
+    <string name="scNullCipherIssueActionGotIt">Got it</string>
 
     <!-- android.net.http Error strings --> <skip />
     <!-- Displayed when a feature code (non-phone number) is dialed and completes successfully. -->
@@ -6041,6 +6050,10 @@
     <!-- Dialog text.  Shown when the user is unable to send a text message from a personal app due to restrictions set
          by their organization, and so must switch to a work app or cancel. [CHAR LIMIT=NONE] -->
     <string name="miniresolver_sms_information">Your organization only allows you to send messages from work apps</string>
+    <!-- Dialog text. Shown as when redirecting Calls from Private Space to the main user. [CHAR LIMIT=NONE] -->
+    <string name="miniresolver_private_space_phone_information">"You can only make phone calls from your personal Phone app. Calls made with personal Phone will be added to your personal call history."</string>
+    <!-- Dialog text. Shown as when redirecting SMS and MMS messages from Private Space to the main user. [CHAR LIMIT=NONE] -->
+    <string name="miniresolver_private_space_messages_information">"You can only send SMS messages from your personal Messages app."</string>
     <!-- Button option. Open the link in the personal browser. [CHAR LIMIT=NONE] -->
     <string name="miniresolver_use_personal_browser">Use personal browser</string>
     <!-- Button option. Open the link in the work browser. [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1e5c5d9..e304027 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -957,12 +957,15 @@
   <java-symbol type="string" name="scCellularNetworkSecurityTitle" />
   <java-symbol type="string" name="scCellularNetworkSecurityLearnMore" />
   <java-symbol type="string" name="scIdentifierDisclosureIssueSummary" />
+  <java-symbol type="string" name="scIdentifierDisclosureIssueSummaryNotification" />
   <java-symbol type="string" name="scIdentifierDisclosureIssueTitle" />
+  <java-symbol type="string" name="scNullCipherIssueActionGotIt" />
   <java-symbol type="string" name="scNullCipherIssueActionLearnMore" />
   <java-symbol type="string" name="scNullCipherIssueActionSettings" />
   <java-symbol type="string" name="scNullCipherIssueEncryptedSummary" />
   <java-symbol type="string" name="scNullCipherIssueEncryptedTitle" />
   <java-symbol type="string" name="scNullCipherIssueNonEncryptedSummary" />
+  <java-symbol type="string" name="scNullCipherIssueNonEncryptedSummaryNotification" />
   <java-symbol type="string" name="scNullCipherIssueNonEncryptedTitle" />
   <java-symbol type="string" name="selected" />
   <java-symbol type="string" name="sendText" />
@@ -1625,6 +1628,8 @@
   <java-symbol type="string" name="miniresolver_switch" />
   <java-symbol type="string" name="miniresolver_call_information" />
   <java-symbol type="string" name="miniresolver_sms_information" />
+  <java-symbol type="string" name="miniresolver_private_space_phone_information" />
+  <java-symbol type="string" name="miniresolver_private_space_messages_information" />
   <java-symbol type="id" name="miniresolver_info_section" />
   <java-symbol type="id" name="miniresolver_info_section_text" />
   <java-symbol type="id" name="button_open" />
@@ -2314,6 +2319,7 @@
   <java-symbol type="string" name="config_primaryLocationTimeZoneProviderPackageName" />
   <java-symbol type="bool" name="config_enableSecondaryLocationTimeZoneProvider" />
   <java-symbol type="string" name="config_secondaryLocationTimeZoneProviderPackageName" />
+  <java-symbol type="bool" name="config_enableTelephonyTimeZoneDetection" />
   <java-symbol type="bool" name="config_supportTelephonyTimeZoneFallback" />
   <java-symbol type="bool" name="config_autoResetAirplaneMode" />
   <java-symbol type="string" name="config_notificationAccessConfirmationActivity" />
@@ -5409,4 +5415,7 @@
   <java-symbol type="integer" name="config_wallpaperFrameRateCompatibility" />
 
   <java-symbol type="integer" name="config_defaultMinEmergencyGestureTapDurationMillis" />
+  <!-- Back swipe thresholds -->
+  <java-symbol type="dimen" name="navigation_edge_action_progress_threshold" />
+  <java-symbol type="dimen" name="back_progress_non_linear_factor" />
 </resources>
diff --git a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
index 9bb064c..62d89f6 100644
--- a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
+++ b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java
@@ -19,10 +19,20 @@
 import static android.os.storage.VolumeInfo.STATE_MOUNTED;
 import static android.os.storage.VolumeInfo.STATE_UNMOUNTED;
 
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Bundle;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.platform.test.annotations.Presubmit;
@@ -35,9 +45,11 @@
 import junit.framework.TestCase;
 
 import org.mockito.Mockito;
+import org.xmlpull.v1.XmlPullParser;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 
 @Presubmit
@@ -93,9 +105,11 @@
     private static final class MockedApplicationPackageManager extends ApplicationPackageManager {
         private boolean mForceAllowOnExternal = false;
         private boolean mAllow3rdPartyOnInternal = true;
+        private HashMap<ApplicationInfo, Resources> mResourcesMap;
 
         public MockedApplicationPackageManager() {
             super(null, null);
+            mResourcesMap = new HashMap<ApplicationInfo, Resources>();
         }
 
         public void setForceAllowOnExternal(boolean forceAllowOnExternal) {
@@ -106,6 +120,10 @@
             mAllow3rdPartyOnInternal = allow3rdPartyOnInternal;
         }
 
+        public void setResourcesForApplication(ApplicationInfo info, Resources resources) {
+            mResourcesMap.put(info, resources);
+        }
+
         @Override
         public boolean isForceAllowOnExternal(Context context) {
             return mForceAllowOnExternal;
@@ -122,6 +140,16 @@
                 StorageManager storageManager, IPackageManager pm) {
             return super.getPackageCandidateVolumes(app, storageManager, pm);
         }
+
+        @Override
+        public Resources getResourcesForApplication(ApplicationInfo app)
+                throws NameNotFoundException {
+            if (mResourcesMap.containsKey(app)) {
+                return mResourcesMap.get(app);
+            }
+
+            return super.getResourcesForApplication(app);
+        }
     }
 
     private StorageManager getMockedStorageManager() {
@@ -254,4 +282,73 @@
             verifyReturnedVolumes(candidates, sAdoptedVol);
         }
     }
+
+    public void testExtractPackageItemInfoAttributes_noServiceInfo() {
+        final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+        assertThat(appPkgMgr.extractPackageItemInfoAttributes(null, null, null,
+                new int[]{})).isNull();
+    }
+
+    public void testExtractPackageItemInfoAttributes_noMetaData() {
+        final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+        final PackageItemInfo packageItemInfo = Mockito.mock(PackageItemInfo.class);
+        assertThat(appPkgMgr.extractPackageItemInfoAttributes(packageItemInfo, null, null,
+                new int[]{})).isNull();
+    }
+
+    public void testExtractPackageItemInfoAttributes_noParser() {
+        final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+        final PackageItemInfo packageItemInfo = Mockito.mock(PackageItemInfo.class);
+        final ApplicationInfo applicationInfo = Mockito.mock(ApplicationInfo.class);
+        when(packageItemInfo.getApplicationInfo()).thenReturn(applicationInfo);
+        assertThat(appPkgMgr.extractPackageItemInfoAttributes(packageItemInfo, null, null,
+                new int[]{})).isNull();
+    }
+
+    public void testExtractPackageItemInfoAttributes_noMetaDataXml() {
+        final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+        final PackageItemInfo packageItemInfo = Mockito.mock(PackageItemInfo.class);
+        final ApplicationInfo applicationInfo = Mockito.mock(ApplicationInfo.class);
+        when(packageItemInfo.getApplicationInfo()).thenReturn(applicationInfo);
+        when(packageItemInfo.loadXmlMetaData(any(), any())).thenReturn(null);
+        assertThat(appPkgMgr.extractPackageItemInfoAttributes(packageItemInfo, null, null,
+                new int[]{})).isNull();
+    }
+
+    public void testExtractPackageItemInfoAttributes_nonMatchingRootTag() throws Exception {
+        final String rootTag = "rootTag";
+        final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+        final PackageItemInfo packageItemInfo = Mockito.mock(PackageItemInfo.class);
+        final ApplicationInfo applicationInfo = Mockito.mock(ApplicationInfo.class);
+        final XmlResourceParser parser = Mockito.mock(XmlResourceParser.class);
+
+        when(packageItemInfo.getApplicationInfo()).thenReturn(applicationInfo);
+        packageItemInfo.metaData = new Bundle();
+        when(packageItemInfo.loadXmlMetaData(any(), any())).thenReturn(parser);
+        when(parser.next()).thenReturn(XmlPullParser.END_DOCUMENT);
+        when(parser.getName()).thenReturn(rootTag + "0");
+        assertThat(appPkgMgr.extractPackageItemInfoAttributes(packageItemInfo, null, rootTag,
+                new int[]{})).isNull();
+    }
+
+    public void testExtractPackageItemInfoAttributes_successfulExtraction() throws Exception {
+        final String rootTag = "rootTag";
+        final MockedApplicationPackageManager appPkgMgr = new MockedApplicationPackageManager();
+        final PackageItemInfo packageItemInfo = Mockito.mock(PackageItemInfo.class);
+        final ApplicationInfo applicationInfo = Mockito.mock(ApplicationInfo.class);
+        final XmlResourceParser parser = Mockito.mock(XmlResourceParser.class);
+        final Resources resources = Mockito.mock(Resources.class);
+        final TypedArray attributes = Mockito.mock(TypedArray.class);
+
+        when(packageItemInfo.getApplicationInfo()).thenReturn(applicationInfo);
+        packageItemInfo.metaData = new Bundle();
+        when(packageItemInfo.loadXmlMetaData(any(), any())).thenReturn(parser);
+        when(parser.next()).thenReturn(XmlPullParser.END_DOCUMENT);
+        when(parser.getName()).thenReturn(rootTag);
+        when(resources.obtainAttributes(any(), any())).thenReturn(attributes);
+        appPkgMgr.setResourcesForApplication(applicationInfo, resources);
+
+        assertThat(appPkgMgr.extractPackageItemInfoAttributes(packageItemInfo, null, rootTag,
+                new int[]{})).isEqualTo(attributes);
+    }
 }
diff --git a/core/tests/coretests/src/android/view/ViewFrameRateTest.java b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
index 4b9aaae..c4ac98b 100644
--- a/core/tests/coretests/src/android/view/ViewFrameRateTest.java
+++ b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
@@ -19,6 +19,7 @@
 import static android.view.Surface.FRAME_RATE_CATEGORY_HIGH;
 import static android.view.Surface.FRAME_RATE_CATEGORY_LOW;
 import static android.view.Surface.FRAME_RATE_CATEGORY_NORMAL;
+import static android.view.Surface.FRAME_RATE_CATEGORY_NO_PREFERENCE;
 import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY;
 import static android.view.flags.Flags.FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY;
 import static android.view.flags.Flags.FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY;
@@ -183,6 +184,7 @@
         mActivityRule.runOnUiThread(() -> {
             frameLayout.setFrameContentVelocity(1f);
             mMovingView.offsetTopAndBottom(100);
+            frameLayout.invalidate();
             runAfterDraw(() -> assertEquals(60f, mViewRoot.getLastPreferredFrameRate(), 0f));
         });
         waitForAfterDraw();
@@ -434,6 +436,80 @@
         waitForAfterDraw();
     }
 
+    /**
+     * A common behavior is for two different views to be invalidated in succession, but
+     * intermittently. We want to treat this as an intermittent invalidation.
+     *
+     * This test will only succeed on non-cuttlefish devices, so it is commented out
+     * for potential manual testing.
+     */
+//    @Test
+    @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
+    public void intermittentDoubleInvalidate() throws Throwable {
+        View parent = (View) mMovingView.getParent();
+        mActivityRule.runOnUiThread(() -> {
+            parent.setWillNotDraw(false);
+            // Make sure the View is large
+            ViewGroup.LayoutParams layoutParams = mMovingView.getLayoutParams();
+            layoutParams.width = parent.getWidth();
+            layoutParams.height = parent.getHeight();
+            mMovingView.setLayoutParams(layoutParams);
+        });
+        waitForFrameRateCategoryToSettle();
+        for (int i = 0; i < 5; i++) {
+            int expectedCategory;
+            if (i < 4) {
+                // not intermittent yet.
+                // It takes 2 frames of intermittency before Views vote as intermittent.
+                // It takes 4 more frames for the category to drop to the next category.
+                expectedCategory =
+                        toolkitFrameRateDefaultNormalReadOnly() ? FRAME_RATE_CATEGORY_NORMAL
+                                : FRAME_RATE_CATEGORY_HIGH;
+            } else {
+                // intermittent
+                expectedCategory = FRAME_RATE_CATEGORY_NORMAL;
+            }
+            mActivityRule.runOnUiThread(() -> {
+                mMovingView.invalidate();
+                runAfterDraw(() -> assertEquals(expectedCategory,
+                        mViewRoot.getLastPreferredFrameRateCategory()));
+            });
+            waitForAfterDraw();
+            mActivityRule.runOnUiThread(() -> {
+                parent.invalidate();
+                runAfterDraw(() -> assertEquals(expectedCategory,
+                        mViewRoot.getLastPreferredFrameRateCategory()));
+            });
+            waitForAfterDraw();
+            Thread.sleep(90);
+        }
+    }
+
+    // When a view has two motions that offset each other, the overall motion
+    // should be canceled and be considered unmoved.
+    @Test
+    @RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
+            FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY
+    })
+    public void sameFrameMotion() throws Throwable {
+        mMovingView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+        waitForFrameRateCategoryToSettle();
+
+        mActivityRule.runOnUiThread(() -> {
+            mMovingView.offsetLeftAndRight(10);
+            mMovingView.offsetLeftAndRight(-10);
+            mMovingView.offsetTopAndBottom(100);
+            mMovingView.offsetTopAndBottom(-100);
+            mMovingView.invalidate();
+            runAfterDraw(() -> {
+                assertEquals(0f, mViewRoot.getLastPreferredFrameRate(), 0f);
+                assertEquals(FRAME_RATE_CATEGORY_NO_PREFERENCE,
+                        mViewRoot.getLastPreferredFrameRateCategory());
+            });
+        });
+        waitForAfterDraw();
+    }
     private void runAfterDraw(@NonNull Runnable runnable) {
         Handler handler = new Handler(Looper.getMainLooper());
         mAfterDrawLatch = new CountDownLatch(1);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.kt b/core/tests/coretests/src/android/window/BackTouchTrackerTest.kt
similarity index 96%
rename from libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.kt
rename to core/tests/coretests/src/android/window/BackTouchTrackerTest.kt
index 6dbb1e2..b7bccd4 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/TouchTrackerTest.kt
+++ b/core/tests/coretests/src/android/window/BackTouchTrackerTest.kt
@@ -13,23 +13,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.wm.shell.back
+package android.window
 
 import android.util.MathUtils
-import android.window.BackEvent
 import org.junit.Assert.assertEquals
 import org.junit.Test
 
-class TouchTrackerTest {
-    private fun linearTouchTracker(): TouchTracker = TouchTracker().apply {
+class BackTouchTrackerTest {
+    private fun linearTouchTracker(): BackTouchTracker = BackTouchTracker().apply {
         setProgressThresholds(MAX_DISTANCE, MAX_DISTANCE, NON_LINEAR_FACTOR)
     }
 
-    private fun nonLinearTouchTracker(): TouchTracker = TouchTracker().apply {
+    private fun nonLinearTouchTracker(): BackTouchTracker = BackTouchTracker().apply {
         setProgressThresholds(LINEAR_DISTANCE, MAX_DISTANCE, NON_LINEAR_FACTOR)
     }
 
-    private fun TouchTracker.assertProgress(expected: Float) {
+    private fun BackTouchTracker.assertProgress(expected: Float) {
         val actualProgress = createProgressEvent().progress
         assertEquals(expected, actualProgress, /* delta = */ 0f)
     }
@@ -243,4 +242,4 @@
         private const val INITIAL_X_LEFT_EDGE = 5f
         private const val INITIAL_X_RIGHT_EDGE = MAX_DISTANCE - INITIAL_X_LEFT_EDGE
     }
-}
\ No newline at end of file
+}
diff --git a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
index 6321e5d..852d696 100644
--- a/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
+++ b/core/tests/coretests/src/android/window/WindowOnBackInvokedDispatcherTest.java
@@ -20,6 +20,8 @@
 import static android.window.OnBackInvokedDispatcher.PRIORITY_OVERLAY;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.atLeast;
@@ -32,10 +34,13 @@
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.view.IWindow;
 import android.view.IWindowSession;
+import android.view.MotionEvent;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -87,6 +92,8 @@
             /* triggerBack = */ false,
             /* swipeEdge = */ BackEvent.EDGE_LEFT,
             /* departingAnimationTarget = */ null);
+    private final MotionEvent mMotionEvent =
+            MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 100, 100, 0);
 
     @Before
     public void setUp() throws Exception {
@@ -95,7 +102,7 @@
         doReturn(true).when(mApplicationInfo).isOnBackInvokedCallbackEnabled();
         doReturn(mApplicationInfo).when(mContext).getApplicationInfo();
 
-        mDispatcher = new WindowOnBackInvokedDispatcher(mContext);
+        mDispatcher = new WindowOnBackInvokedDispatcher(mContext, Looper.getMainLooper());
         mDispatcher.attachToWindow(mWindowSession, mWindow, null);
     }
 
@@ -377,4 +384,39 @@
         verify(mCallback1, never()).onBackInvoked();
         verify(mCallback1).onBackCancelled();
     }
+
+    @Test
+    public void updatesDispatchingState() throws RemoteException {
+        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1);
+        OnBackInvokedCallbackInfo callbackInfo = assertSetCallbackInfo();
+
+        callbackInfo.getCallback().onBackStarted(mBackEvent);
+        waitForIdle();
+        assertTrue(mDispatcher.isDispatching());
+
+        callbackInfo.getCallback().onBackInvoked();
+        waitForIdle();
+        assertFalse(mDispatcher.isDispatching());
+    }
+
+    @Test
+    public void handlesMotionEvent() throws RemoteException {
+        mDispatcher.registerOnBackInvokedCallback(PRIORITY_DEFAULT, mCallback1);
+        OnBackInvokedCallbackInfo callbackInfo = assertSetCallbackInfo();
+
+        // Send motion event in View's main thread.
+        final Handler main = Handler.getMain();
+        main.runWithScissors(() -> mDispatcher.onMotionEvent(mMotionEvent), 100);
+        assertFalse(mDispatcher.mTouchTracker.isActive());
+
+        callbackInfo.getCallback().onBackStarted(mBackEvent);
+        waitForIdle();
+        assertTrue(mDispatcher.isDispatching());
+        assertTrue(mDispatcher.mTouchTracker.isActive());
+
+        main.runWithScissors(() -> mDispatcher.onMotionEvent(mMotionEvent), 100);
+        waitForIdle();
+        // onBackPressed is called from animator, so it can happen more than once.
+        verify(mCallback1, atLeast(1)).onBackProgressed(any());
+    }
 }
diff --git a/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java b/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
index 9cb9122..03cb17e 100644
--- a/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
+++ b/core/tests/packagemonitortests/src/com/android/internal/content/PackageMonitorTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -95,6 +96,16 @@
     }
 
     @Test
+    public void testPackageMonitorNotRegisterWithoutSupportPackageRestartQuery() throws Exception {
+        PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor(false));
+
+        spyPackageMonitor.register(mMockContext, UserHandle.ALL, mMockHandler);
+
+        verify(mMockContext, never()).registerReceiverAsUser(any(), eq(UserHandle.ALL), any(),
+                eq(null), eq(mMockHandler));
+    }
+
+    @Test
     public void testPackageMonitorDoHandlePackageEventUidRemoved() throws Exception {
         PackageMonitor spyPackageMonitor = spy(new TestPackageMonitor());
 
@@ -471,5 +482,12 @@
     }
 
     public static class TestPackageMonitor extends PackageMonitor {
+        public TestPackageMonitor(boolean b) {
+            super(b);
+        }
+
+        public TestPackageMonitor() {
+            super();
+        }
     }
 }
diff --git a/graphics/java/android/framework_graphics.aconfig b/graphics/java/android/framework_graphics.aconfig
index 4ab09eb..0b9e72d 100644
--- a/graphics/java/android/framework_graphics.aconfig
+++ b/graphics/java/android/framework_graphics.aconfig
@@ -16,3 +16,11 @@
      description: "Feature flag for YUV image compress to Ultra HDR."
      bug: "308978825"
 }
+
+flag {
+    name: "icon_load_drawable_return_null_when_uri_decode_fails"
+    is_exported: true
+    namespace: "core_graphics"
+    description: "Return null when decode from URI fails in Icon.loadDrawable()"
+    bug: "335878768"
+}
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index b291f93..579ac60 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -43,6 +43,7 @@
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.LayoutDirection;
+import android.util.Log;
 import android.util.TypedValue;
 import android.view.Gravity;
 
@@ -138,6 +139,9 @@
      */
     @Deprecated
     public BitmapDrawable(Bitmap bitmap) {
+        if (bitmap == null) {
+            Log.w(TAG, "BitmapDrawable created with null Bitmap");
+        }
         init(new BitmapState(bitmap), null);
     }
 
@@ -146,6 +150,9 @@
      * the display metrics of the resources.
      */
     public BitmapDrawable(Resources res, Bitmap bitmap) {
+        if (bitmap == null) {
+            Log.w(TAG, "BitmapDrawable created with null Bitmap");
+        }
         init(new BitmapState(bitmap), res);
     }
 
@@ -177,7 +184,7 @@
         } finally {
             init(new BitmapState(bitmap), res);
             if (mBitmapState.mBitmap == null) {
-                android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
+                Log.w(TAG, "BitmapDrawable cannot decode " + filepath);
             }
         }
     }
@@ -210,7 +217,7 @@
         } finally {
             init(new BitmapState(bitmap), res);
             if (mBitmapState.mBitmap == null) {
-                android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
+                Log.w(TAG, "BitmapDrawable cannot decode " + is);
             }
         }
     }
@@ -1073,4 +1080,6 @@
                 mBitmapState.mBlendMode);
         computeBitmapSize();
     }
+
+    private static final String TAG = "BitmapDrawable";
 }
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index f359025..c3aaf98 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -19,6 +19,8 @@
 import static android.content.Context.CONTEXT_INCLUDE_CODE;
 import static android.content.Context.CONTEXT_RESTRICTED;
 
+import static com.android.graphics.flags.Flags.iconLoadDrawableReturnNullWhenUriDecodeFails;
+
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
@@ -494,15 +496,28 @@
             case TYPE_URI:
                 InputStream is = getUriInputStream(context);
                 if (is != null) {
-                    return new BitmapDrawable(context.getResources(),
-                            fixMaxBitmapSize(BitmapFactory.decodeStream(is)));
+                    final Bitmap bitmap = BitmapFactory.decodeStream(is);
+                    if (bitmap == null) {
+                        Log.w(TAG, "Unable to decode image from URI: " + getUriString());
+                        if (iconLoadDrawableReturnNullWhenUriDecodeFails()) {
+                            return null;
+                        }
+                    }
+                    return new BitmapDrawable(context.getResources(), fixMaxBitmapSize(bitmap));
                 }
                 break;
             case TYPE_URI_ADAPTIVE_BITMAP:
                 is = getUriInputStream(context);
                 if (is != null) {
+                    final Bitmap bitmap = BitmapFactory.decodeStream(is);
+                    if (bitmap == null) {
+                        Log.w(TAG, "Unable to decode image from URI: " + getUriString());
+                        if (iconLoadDrawableReturnNullWhenUriDecodeFails()) {
+                            return null;
+                        }
+                    }
                     return new AdaptiveIconDrawable(null, new BitmapDrawable(context.getResources(),
-                            fixMaxBitmapSize(BitmapFactory.decodeStream(is))));
+                            fixMaxBitmapSize(bitmap)));
                 }
                 break;
         }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 46a3e7f..89d3058 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -67,7 +67,6 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.SystemProperties;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
@@ -113,8 +112,7 @@
 public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmentCallback,
         ActivityEmbeddingComponent, DividerPresenter.DragEventCallback {
     static final String TAG = "SplitController";
-    static final boolean ENABLE_SHELL_TRANSITIONS =
-            SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
+    static final boolean ENABLE_SHELL_TRANSITIONS = true;
 
     // TODO(b/243518738): Move to WM Extensions if we have requirement of overlay without
     //  association. It's not set in WM Extensions nor Wm Jetpack library currently.
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 5c978e2..89781fd 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -210,6 +210,7 @@
         "androidx.recyclerview_recyclerview",
         "kotlinx-coroutines-android",
         "kotlinx-coroutines-core",
+        "//frameworks/libs/systemui:com_android_systemui_shared_flags_lib",
         "//frameworks/libs/systemui:iconloader_base",
         "com_android_wm_shell_flags_lib",
         "com.android.window.flags.window-aconfig-java",
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/IShellTransitions.aidl b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/IShellTransitions.aidl
index 526407e..3256abf 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/IShellTransitions.aidl
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/IShellTransitions.aidl
@@ -28,13 +28,14 @@
 interface IShellTransitions {
 
     /**
-     * Registers a remote transition handler.
+     * Registers a remote transition handler for all operations excluding takeovers (see
+     * registerRemoteForTakeover()).
      */
     oneway void registerRemote(in TransitionFilter filter,
             in RemoteTransition remoteTransition) = 1;
 
     /**
-     * Unregisters a remote transition handler.
+     * Unregisters a remote transition handler for all operations.
      */
     oneway void unregisterRemote(in RemoteTransition remoteTransition) = 2;
 
@@ -52,4 +53,10 @@
      * Returns a container surface for the home root task.
      */
     SurfaceControl getHomeTaskOverlayContainer() = 5;
+
+    /**
+     * Registers a remote transition for takeover operations only.
+     */
+    oneway void registerRemoteForTakeover(in TransitionFilter filter,
+            in RemoteTransition remoteTransition) = 6;
 }
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/ShellTransitions.java b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/ShellTransitions.java
index 5e49f55..6d4ab4c 100644
--- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/ShellTransitions.java
+++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/ShellTransitions.java
@@ -28,13 +28,20 @@
 @ExternalThread
 public interface ShellTransitions {
     /**
-     * Registers a remote transition.
+     * Registers a remote transition for all operations excluding takeovers (see
+     * {@link ShellTransitions#registerRemoteForTakeover(TransitionFilter, RemoteTransition)}).
      */
     default void registerRemote(@NonNull TransitionFilter filter,
             @NonNull RemoteTransition remoteTransition) {}
 
     /**
-     * Unregisters a remote transition.
+     * Registers a remote transition for takeover operations only.
+     */
+    default void registerRemoteForTakeover(@NonNull TransitionFilter filter,
+            @NonNull RemoteTransition remoteTransition) {}
+
+    /**
+     * Unregisters a remote transition for all operations.
      */
     default void unregisterRemote(@NonNull RemoteTransition remoteTransition) {}
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java
index 2643211..196f89d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java
@@ -49,9 +49,9 @@
             @BackEvent.SwipeEdge int swipeEdge);
 
     /**
-     * Called when the input pointers are pilfered.
+     * Called when the back swipe threshold is crossed.
      */
-    void onPilferPointers();
+    void onThresholdCrossed();
 
     /**
      * Sets whether the back gesture is past the trigger threshold or not.
@@ -101,4 +101,10 @@
      * @param customizer the controller to control system bar color.
      */
     void setStatusBarCustomizer(StatusBarCustomizer customizer);
+
+    /**
+     * Set a callback to pilfer pointers.
+     * @param pilferCallback the callback to pilfer pointers.
+     */
+    void setPilferPointerCallback(Runnable pilferCallback);
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index d3fe4f8..163a896 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -22,9 +22,6 @@
 import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
 import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SuppressLint;
@@ -46,7 +43,6 @@
 import android.provider.Settings.Global;
 import android.util.DisplayMetrics;
 import android.util.Log;
-import android.util.MathUtils;
 import android.view.IRemoteAnimationRunner;
 import android.view.InputDevice;
 import android.view.KeyCharacterMap;
@@ -57,6 +53,7 @@
 import android.window.BackEvent;
 import android.window.BackMotionEvent;
 import android.window.BackNavigationInfo;
+import android.window.BackTouchTracker;
 import android.window.IBackAnimationFinishedCallback;
 import android.window.IBackAnimationRunner;
 import android.window.IOnBackInvokedCallback;
@@ -118,7 +115,8 @@
     /** Tracks if we should start the back gesture on the next motion move event */
     private boolean mShouldStartOnNextMoveEvent = false;
     private boolean mOnBackStartDispatched = false;
-    private boolean mPointerPilfered = false;
+    private boolean mThresholdCrossed = false;
+    private boolean mPointersPilfered = false;
     private final boolean mRequirePointerPilfer;
 
     private final FlingAnimationUtils mFlingAnimationUtils;
@@ -139,13 +137,13 @@
     /**
      * Tracks the current user back gesture.
      */
-    private TouchTracker mCurrentTracker = new TouchTracker();
+    private BackTouchTracker mCurrentTracker = new BackTouchTracker();
 
     /**
      * Tracks the next back gesture in case a new user gesture has started while the back animation
      * (and navigation) associated with {@link #mCurrentTracker} have not yet finished.
      */
-    private TouchTracker mQueuedTracker = new TouchTracker();
+    private BackTouchTracker mQueuedTracker = new BackTouchTracker();
 
     private final Runnable mAnimationTimeoutRunnable = () -> {
         ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Animation didn't finish in %d ms. Resetting...",
@@ -189,6 +187,7 @@
     // Keep previous navigation type before remove mBackNavigationInfo.
     @BackNavigationInfo.BackTargetType
     private int mPreviousNavigationType;
+    private Runnable mPilferPointerCallback;
 
     public BackAnimationController(
             @NonNull ShellInit shellInit,
@@ -335,8 +334,8 @@
         }
 
         @Override
-        public void onPilferPointers() {
-            BackAnimationController.this.onPilferPointers();
+        public void onThresholdCrossed() {
+            BackAnimationController.this.onThresholdCrossed();
         }
 
         @Override
@@ -358,6 +357,13 @@
             mCustomizer = customizer;
             mAnimationBackground.setStatusBarCustomizer(customizer);
         }
+
+        @Override
+        public void setPilferPointerCallback(Runnable callback) {
+            mShellExecutor.execute(() -> {
+                mPilferPointerCallback = callback;
+            });
+        }
     }
 
     private static class IBackAnimationImpl extends IBackAnimation.Stub
@@ -414,20 +420,23 @@
         mShellBackAnimationRegistry.unregisterAnimation(type);
     }
 
-    private TouchTracker getActiveTracker() {
+    private BackTouchTracker getActiveTracker() {
         if (mCurrentTracker.isActive()) return mCurrentTracker;
         if (mQueuedTracker.isActive()) return mQueuedTracker;
         return null;
     }
 
     @VisibleForTesting
-    void onPilferPointers() {
-        mPointerPilfered = true;
+    public void onThresholdCrossed() {
+        mThresholdCrossed = true;
         // Dispatch onBackStarted, only to app callbacks.
         // System callbacks will receive onBackStarted when the remote animation starts.
-        if (!shouldDispatchToAnimator() && mActiveCallback != null) {
+        final boolean shouldDispatchToAnimator = shouldDispatchToAnimator();
+        if (!shouldDispatchToAnimator && mActiveCallback != null) {
             mCurrentTracker.updateStartLocation();
             tryDispatchOnBackStarted(mActiveCallback, mCurrentTracker.createStartEvent(null));
+        } else if (shouldDispatchToAnimator) {
+            tryPilferPointers();
         }
     }
 
@@ -443,7 +452,7 @@
             int keyAction,
             @BackEvent.SwipeEdge int swipeEdge) {
 
-        TouchTracker activeTouchTracker = getActiveTracker();
+        BackTouchTracker activeTouchTracker = getActiveTracker();
         if (activeTouchTracker != null) {
             activeTouchTracker.update(touchX, touchY, velocityX, velocityY);
         }
@@ -487,7 +496,7 @@
             // onBackCancelled event, let's interrupt it and start animating a new back gesture
             resetTouchTracker();
         }
-        TouchTracker touchTracker;
+        BackTouchTracker touchTracker;
         if (mCurrentTracker.isInInitialState()) {
             touchTracker = mCurrentTracker;
         } else if (mQueuedTracker.isInInitialState()) {
@@ -498,7 +507,7 @@
             return;
         }
         touchTracker.setGestureStartLocation(touchX, touchY, swipeEdge);
-        touchTracker.setState(TouchTracker.TouchTrackerState.ACTIVE);
+        touchTracker.setState(BackTouchTracker.TouchTrackerState.ACTIVE);
         mBackGestureStarted = true;
 
         if (interruptCancelPostCommitAnimation) {
@@ -514,7 +523,7 @@
         }
     }
 
-    private void startBackNavigation(@NonNull TouchTracker touchTracker) {
+    private void startBackNavigation(@NonNull BackTouchTracker touchTracker) {
         try {
             startLatencyTracking();
             mBackNavigationInfo = mActivityTaskManager.startBackNavigation(
@@ -527,7 +536,7 @@
     }
 
     private void onBackNavigationInfoReceived(@Nullable BackNavigationInfo backNavigationInfo,
-            @NonNull TouchTracker touchTracker) {
+            @NonNull BackTouchTracker touchTracker) {
         ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Received backNavigationInfo:%s", backNavigationInfo);
         if (backNavigationInfo == null) {
             ProtoLog.e(WM_SHELL_BACK_PREVIEW, "Received BackNavigationInfo is null.");
@@ -540,6 +549,7 @@
             if (!mShellBackAnimationRegistry.startGesture(backType)) {
                 mActiveCallback = null;
             }
+            tryPilferPointers();
         } else {
             mActiveCallback = mBackNavigationInfo.getOnBackInvokedCallback();
             // App is handling back animation. Cancel system animation latency tracking.
@@ -588,12 +598,22 @@
                 && mBackNavigationInfo.isPrepareRemoteAnimation();
     }
 
+    private void tryPilferPointers() {
+        if (mPointersPilfered || !mThresholdCrossed) {
+            return;
+        }
+        if (mPilferPointerCallback != null) {
+            mPilferPointerCallback.run();
+        }
+        mPointersPilfered = true;
+    }
+
     private void tryDispatchOnBackStarted(
             IOnBackInvokedCallback callback,
             BackMotionEvent backEvent) {
         if (mOnBackStartDispatched
                 || callback == null
-                || (!mPointerPilfered && mRequirePointerPilfer)) {
+                || (!mThresholdCrossed && mRequirePointerPilfer)) {
             return;
         }
         dispatchOnBackStarted(callback, backEvent);
@@ -613,79 +633,6 @@
         }
     }
 
-
-    /**
-     * Allows us to manage the fling gesture, it smoothly animates the current progress value to
-     * the final position, calculated based on the current velocity.
-     *
-     * @param callback the callback to be invoked when the animation ends.
-     */
-    private void dispatchOrAnimateOnBackInvoked(IOnBackInvokedCallback callback,
-            @NonNull TouchTracker touchTracker) {
-        if (callback == null) {
-            return;
-        }
-
-        boolean animationStarted = false;
-
-        if (mBackNavigationInfo != null && mBackNavigationInfo.isAnimationCallback()) {
-
-            final BackMotionEvent backMotionEvent = touchTracker.createProgressEvent();
-            if (backMotionEvent != null) {
-                // Constraints - absolute values
-                float minVelocity = mFlingAnimationUtils.getMinVelocityPxPerSecond();
-                float maxVelocity = mFlingAnimationUtils.getHighVelocityPxPerSecond();
-                float maxX = touchTracker.getMaxDistance(); // px
-                float maxFlingDistance = maxX * MAX_FLING_PROGRESS; // px
-
-                // Current state
-                float currentX = backMotionEvent.getTouchX();
-                float velocity = MathUtils.constrain(backMotionEvent.getVelocityX(),
-                        -maxVelocity, maxVelocity);
-
-                // Target state
-                float animationFaction = velocity / maxVelocity; // value between -1 and 1
-                float flingDistance = animationFaction * maxFlingDistance; // px
-                float endX = MathUtils.constrain(currentX + flingDistance, 0f, maxX);
-
-                if (!Float.isNaN(endX)
-                        && currentX != endX
-                        && Math.abs(velocity) >= minVelocity) {
-                    ValueAnimator animator = ValueAnimator.ofFloat(currentX, endX);
-
-                    mFlingAnimationUtils.apply(
-                            /* animator = */ animator,
-                            /* currValue = */ currentX,
-                            /* endValue = */ endX,
-                            /* velocity = */ velocity,
-                            /* maxDistance = */ maxFlingDistance
-                    );
-
-                    animator.addUpdateListener(animation -> {
-                        Float animatedValue = (Float) animation.getAnimatedValue();
-                        float progress = touchTracker.getProgress(animatedValue);
-                        final BackMotionEvent backEvent = touchTracker.createProgressEvent(
-                                progress);
-                        dispatchOnBackProgressed(mActiveCallback, backEvent);
-                    });
-
-                    animator.addListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            dispatchOnBackInvoked(callback);
-                        }
-                    });
-                    animator.start();
-                    animationStarted = true;
-                }
-            }
-        }
-
-        if (!animationStarted) {
-            dispatchOnBackInvoked(callback);
-        }
-    }
-
     private void dispatchOnBackInvoked(IOnBackInvokedCallback callback) {
         if (callback == null) {
             return;
@@ -714,7 +661,7 @@
 
     private void dispatchOnBackProgressed(IOnBackInvokedCallback callback,
             BackMotionEvent backEvent) {
-        if (callback == null) {
+        if (callback == null || !shouldDispatchToAnimator()) {
             return;
         }
         try {
@@ -728,7 +675,14 @@
      * Sets to true when the back gesture has passed the triggering threshold, false otherwise.
      */
     public void setTriggerBack(boolean triggerBack) {
-        TouchTracker activeBackGestureInfo = getActiveTracker();
+        if (mActiveCallback != null) {
+            try {
+                mActiveCallback.setTriggerBack(triggerBack);
+            } catch (RemoteException e) {
+                Log.e(TAG, "remote setTriggerBack error: ", e);
+            }
+        }
+        BackTouchTracker activeBackGestureInfo = getActiveTracker();
         if (activeBackGestureInfo != null) {
             activeBackGestureInfo.setTriggerBack(triggerBack);
         }
@@ -742,7 +696,7 @@
         mQueuedTracker.setProgressThresholds(linearDistance, maxDistance, nonLinearFactor);
     }
 
-    private void invokeOrCancelBack(@NonNull TouchTracker touchTracker) {
+    private void invokeOrCancelBack(@NonNull BackTouchTracker touchTracker) {
         // Make a synchronized call to core before dispatch back event to client side.
         // If the close transition happens before the core receives onAnimationFinished, there will
         // play a second close animation for that transition.
@@ -758,7 +712,7 @@
         if (mBackNavigationInfo != null) {
             final IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback();
             if (touchTracker.getTriggerBack()) {
-                dispatchOrAnimateOnBackInvoked(callback, touchTracker);
+                dispatchOnBackInvoked(callback);
             } else {
                 tryDispatchOnBackCancelled(callback);
             }
@@ -770,7 +724,7 @@
      * Called when the gesture is released, then it could start the post commit animation.
      */
     private void onGestureFinished() {
-        TouchTracker activeTouchTracker = getActiveTracker();
+        BackTouchTracker activeTouchTracker = getActiveTracker();
         if (!mBackGestureStarted || activeTouchTracker == null) {
             // This can happen when an unfinished gesture has been reset in resetTouchTracker
             ProtoLog.d(WM_SHELL_BACK_PREVIEW,
@@ -780,8 +734,11 @@
         boolean triggerBack = activeTouchTracker.getTriggerBack();
         ProtoLog.d(WM_SHELL_BACK_PREVIEW, "onGestureFinished() mTriggerBack == %s", triggerBack);
 
+        // Reset gesture states.
+        mThresholdCrossed = false;
+        mPointersPilfered = false;
         mBackGestureStarted = false;
-        activeTouchTracker.setState(TouchTracker.TouchTrackerState.FINISHED);
+        activeTouchTracker.setState(BackTouchTracker.TouchTrackerState.FINISHED);
 
         if (mPostCommitAnimationInProgress) {
             ProtoLog.w(WM_SHELL_BACK_PREVIEW, "Animation is still running");
@@ -839,7 +796,7 @@
         if (mCurrentTracker.getTriggerBack()) {
             // notify gesture finished
             mBackNavigationInfo.onBackGestureFinished(true);
-            dispatchOrAnimateOnBackInvoked(mActiveCallback, mCurrentTracker);
+            dispatchOnBackInvoked(mActiveCallback);
         } else {
             tryDispatchOnBackCancelled(mActiveCallback);
         }
@@ -882,10 +839,11 @@
     }
 
     /**
-     * Resets the TouchTracker and potentially starts a new back navigation in case one is queued
+     * Resets the BackTouchTracker and potentially starts a new back navigation in case one
+     * is queued.
      */
     private void resetTouchTracker() {
-        TouchTracker temp = mCurrentTracker;
+        BackTouchTracker temp = mCurrentTracker;
         mCurrentTracker = mQueuedTracker;
         temp.reset();
         mQueuedTracker = temp;
@@ -928,7 +886,8 @@
         mApps = null;
         mShouldStartOnNextMoveEvent = false;
         mOnBackStartDispatched = false;
-        mPointerPilfered = false;
+        mThresholdCrossed = false;
+        mPointersPilfered = false;
         mShellBackAnimationRegistry.resetDefaultCrossActivity();
         cancelLatencyTracking();
         if (mBackNavigationInfo != null) {
@@ -1076,7 +1035,7 @@
         pw.println(prefix + "  mBackGestureStarted=" + mBackGestureStarted);
         pw.println(prefix + "  mPostCommitAnimationInProgress=" + mPostCommitAnimationInProgress);
         pw.println(prefix + "  mShouldStartOnNextMoveEvent=" + mShouldStartOnNextMoveEvent);
-        pw.println(prefix + "  mPointerPilfered=" + mPointerPilfered);
+        pw.println(prefix + "  mPointerPilfered=" + mThresholdCrossed);
         pw.println(prefix + "  mRequirePointerPilfer=" + mRequirePointerPilfer);
         pw.println(prefix + "  mCurrentTracker state:");
         mCurrentTracker.dump(pw, prefix + "    ");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
index 808c212..037b1ec 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
@@ -20,6 +20,7 @@
 import android.animation.ValueAnimator
 import android.content.Context
 import android.content.res.Configuration
+import android.graphics.Color
 import android.graphics.Matrix
 import android.graphics.PointF
 import android.graphics.Rect
@@ -35,6 +36,7 @@
 import android.view.animation.Interpolator
 import android.window.BackEvent
 import android.window.BackMotionEvent
+import android.window.BackNavigationInfo
 import android.window.BackProgressAnimator
 import android.window.IOnBackInvokedCallback
 import com.android.internal.jank.Cuj
@@ -67,6 +69,7 @@
     private val currentEnteringRect = RectF()
 
     private val backAnimRect = Rect()
+    private val cropRect = Rect()
 
     private var cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
 
@@ -95,6 +98,10 @@
     private var maxScrimAlpha: Float = 0f
 
     private var isLetterboxed = false
+    private var enteringHasSameLetterbox = false
+    private var leftLetterboxLayer: SurfaceControl? = null
+    private var rightLetterboxLayer: SurfaceControl? = null
+    private var letterboxColor: Int = 0
 
     override fun onConfigurationChanged(newConfiguration: Configuration) {
         cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
@@ -115,8 +122,12 @@
 
         transaction.setAnimationTransaction()
         isLetterboxed = closingTarget!!.taskInfo.appCompatTaskInfo.topActivityBoundsLetterboxed
-        if (isLetterboxed) {
-            // Include letterbox in back animation
+        enteringHasSameLetterbox = isLetterboxed &&
+                closingTarget!!.localBounds.equals(enteringTarget!!.localBounds)
+
+        if (isLetterboxed && !enteringHasSameLetterbox) {
+            // Play animation with letterboxes, if closing and entering target have mismatching
+            // letterboxes
             backAnimRect.set(closingTarget!!.windowConfiguration.bounds)
         } else {
             // otherwise play animation on localBounds only
@@ -144,12 +155,25 @@
         targetEnteringRect.set(startEnteringRect)
         targetEnteringRect.scaleCentered(MAX_SCALE)
 
-        // Draw background with task background color.
+        // Draw background with task background color (or letterbox color).
+        val backgroundColor = if (isLetterboxed) {
+            letterboxColor
+        } else {
+            enteringTarget!!.taskInfo.taskDescription!!.backgroundColor
+        }
         background.ensureBackground(
-            closingTarget!!.windowConfiguration.bounds,
-            enteringTarget!!.taskInfo.taskDescription!!.backgroundColor, transaction
+            closingTarget!!.windowConfiguration.bounds, backgroundColor, transaction
         )
         ensureScrimLayer()
+        if (isLetterboxed && enteringHasSameLetterbox) {
+            // crop left and right letterboxes
+            cropRect.set(closingTarget!!.localBounds.left, 0, closingTarget!!.localBounds.right,
+                    closingTarget!!.windowConfiguration.bounds.height())
+            // and add fake letterbox square surfaces instead
+            ensureLetterboxes()
+        } else {
+            cropRect.set(backAnimRect)
+        }
         applyTransaction()
     }
 
@@ -249,18 +273,25 @@
         }
         finishCallback = null
         removeScrimLayer()
+        removeLetterbox()
         isLetterboxed = false
+        enteringHasSameLetterbox = false
     }
 
     private fun applyTransform(leash: SurfaceControl?, rect: RectF, alpha: Float) {
         if (leash == null || !leash.isValid) return
         val scale = rect.width() / backAnimRect.width()
         transformMatrix.reset()
-        transformMatrix.setScale(scale, scale)
+        val scalePivotX = if (isLetterboxed && enteringHasSameLetterbox) {
+            closingTarget!!.localBounds.left.toFloat()
+        } else {
+            0f
+        }
+        transformMatrix.setScale(scale, scale, scalePivotX, 0f)
         transformMatrix.postTranslate(rect.left, rect.top)
         transaction.setAlpha(leash, alpha)
             .setMatrix(leash, transformMatrix, tmpFloat9)
-            .setCrop(leash, backAnimRect)
+            .setCrop(leash, cropRect)
             .setCornerRadius(leash, cornerRadius)
     }
 
@@ -297,15 +328,73 @@
     }
 
     private fun removeScrimLayer() {
-        scrimLayer?.let {
-            if (it.isValid) {
-                transaction.remove(it)
-                applyTransaction()
-            }
-        }
+        if (removeLayer(scrimLayer)) applyTransaction()
         scrimLayer = null
     }
 
+    /**
+     * Adds two "fake" letterbox square surfaces to the left and right of the localBounds of the
+     * closing target
+     */
+    private fun ensureLetterboxes() {
+        closingTarget?.let { t ->
+            if (t.localBounds.left != 0 && leftLetterboxLayer == null) {
+                val bounds = Rect(0, t.windowConfiguration.bounds.top, t.localBounds.left,
+                        t.windowConfiguration.bounds.bottom)
+                leftLetterboxLayer = ensureLetterbox(bounds)
+            }
+            if (t.localBounds.right != t.windowConfiguration.bounds.right &&
+                    rightLetterboxLayer == null) {
+                val bounds = Rect(t.localBounds.right, t.windowConfiguration.bounds.top,
+                        t.windowConfiguration.bounds.right, t.windowConfiguration.bounds.bottom)
+                rightLetterboxLayer = ensureLetterbox(bounds)
+            }
+        }
+    }
+
+    private fun ensureLetterbox(bounds: Rect): SurfaceControl {
+        val letterboxBuilder = SurfaceControl.Builder()
+                .setName("Cross-Activity back animation letterbox")
+                .setCallsite("CrossActivityBackAnimation")
+                .setColorLayer()
+                .setOpaque(true)
+                .setHidden(false)
+
+        rootTaskDisplayAreaOrganizer.attachToDisplayArea(Display.DEFAULT_DISPLAY, letterboxBuilder)
+        val layer = letterboxBuilder.build()
+        val colorComponents = floatArrayOf(Color.red(letterboxColor) / 255f,
+                Color.green(letterboxColor) / 255f, Color.blue(letterboxColor) / 255f)
+        transaction
+                .setColor(layer, colorComponents)
+                .setCrop(layer, bounds)
+                .setRelativeLayer(layer, closingTarget!!.leash, 1)
+                .show(layer)
+        return layer
+    }
+
+    private fun removeLetterbox() {
+        if (removeLayer(leftLetterboxLayer) || removeLayer(rightLetterboxLayer)) applyTransaction()
+        leftLetterboxLayer = null
+        rightLetterboxLayer = null
+    }
+
+    private fun removeLayer(layer: SurfaceControl?): Boolean {
+        layer?.let {
+            if (it.isValid) {
+                transaction.remove(it)
+                return true
+            }
+        }
+        return false
+    }
+
+    override fun prepareNextAnimation(
+            animationInfo: BackNavigationInfo.CustomAnimationInfo?,
+            letterboxColor: Int
+    ): Boolean {
+        this.letterboxColor = letterboxColor
+        return false
+    }
 
     private inner class Callback : IOnBackInvokedCallback.Default() {
         override fun onBackStarted(backMotionEvent: BackMotionEvent) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
index 838dab4..e27b40e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
@@ -271,7 +271,8 @@
 
     /** Load customize animation before animation start. */
     @Override
-    public boolean prepareNextAnimation(BackNavigationInfo.CustomAnimationInfo animationInfo) {
+    public boolean prepareNextAnimation(BackNavigationInfo.CustomAnimationInfo animationInfo,
+            int letterboxColor) {
         if (animationInfo == null) {
             return false;
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java
index 8a0daaa..9cd193b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimation.java
@@ -42,11 +42,12 @@
     public abstract BackAnimationRunner getRunner();
 
     /**
-     * Prepare the next animation with customized animation.
+     * Prepare the next animation.
      *
      * @return true if this type of back animation should override the default.
      */
-    public boolean prepareNextAnimation(BackNavigationInfo.CustomAnimationInfo animationInfo) {
+    public boolean prepareNextAnimation(BackNavigationInfo.CustomAnimationInfo animationInfo,
+            int letterboxColor) {
         return false;
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
index 7a6032c..6fafa75 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
@@ -154,11 +154,14 @@
         if (type == BackNavigationInfo.TYPE_CROSS_ACTIVITY && mAnimationDefinition.contains(type)) {
             if (mCustomizeActivityAnimation != null
                     && mCustomizeActivityAnimation.prepareNextAnimation(
-                            backNavigationInfo.getCustomAnimationInfo())) {
+                            backNavigationInfo.getCustomAnimationInfo(), 0)) {
                 mAnimationDefinition.get(type).resetWaitingAnimation();
                 mAnimationDefinition.set(
                         BackNavigationInfo.TYPE_CROSS_ACTIVITY,
                         mCustomizeActivityAnimation.getRunner());
+            } else if (mDefaultCrossActivityAnimation != null) {
+                mDefaultCrossActivityAnimation.prepareNextAnimation(null,
+                        backNavigationInfo.getLetterboxColor());
             }
         }
         BackAnimationRunner runner = mAnimationDefinition.get(type);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index dae62ac..30eb8b5d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -18,6 +18,7 @@
 
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
@@ -109,7 +110,7 @@
     }
 
     /** Inflates split decor surface on the root surface. */
-    public void inflate(Context context, SurfaceControl rootLeash, Rect rootBounds) {
+    public void inflate(Context context, SurfaceControl rootLeash) {
         if (mIconLeash != null && mViewHost != null) {
             return;
         }
@@ -128,13 +129,12 @@
         final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                 0 /* width */, 0 /* height */, TYPE_APPLICATION_OVERLAY,
                 FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
-        lp.width = rootBounds.width();
-        lp.height = rootBounds.height();
+        lp.width = mIconSize;
+        lp.height = mIconSize;
         lp.token = new Binder();
         lp.setTitle(TAG);
         lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
-        // TODO(b/189839391): Set INPUT_FEATURE_NO_INPUT_CHANNEL after WM supports
-        //  TRUSTED_OVERLAY for windowless window without input channel.
+        lp.inputFeatures |= INPUT_FEATURE_NO_INPUT_CHANNEL;
         mViewHost.setView(rootLayout, lp);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index c625b69..a7829c9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -27,6 +27,7 @@
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 import static android.window.TransitionInfo.FLAG_TRANSLUCENT;
 
+import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_CAN_HAND_OFF_ANIMATION;
 import static com.android.wm.shell.util.SplitBounds.KEY_EXTRA_SPLIT_BOUNDS;
 
 import android.annotation.Nullable;
@@ -54,6 +55,7 @@
 import android.window.TaskSnapshot;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
+import android.window.WindowAnimationState;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
@@ -283,6 +285,7 @@
         private IBinder mTransition = null;
         private boolean mKeyguardLocked = false;
         private boolean mWillFinishToHome = false;
+        private Transitions.TransitionHandler mTakeoverHandler = null;
 
         /** The animation is idle, waiting for the user to choose a task to switch to. */
         private static final int STATE_NORMAL = 0;
@@ -576,9 +579,13 @@
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                     "Applying transaction=%d", t.getId());
             t.apply();
-            Bundle b = new Bundle(1 /*capacity*/);
+
+            mTakeoverHandler = mTransitions.getHandlerForTakeover(mTransition, info);
+
+            Bundle b = new Bundle(2 /*capacity*/);
             b.putParcelable(KEY_EXTRA_SPLIT_BOUNDS,
                     mRecentTasksController.getSplitBoundsForTaskId(closingSplitTaskId));
+            b.putBoolean(KEY_EXTRA_SHELL_CAN_HAND_OFF_ANIMATION, mTakeoverHandler != null);
             try {
                 ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                         "[%d] RecentsController.start: calling onAnimationStart with %d apps",
@@ -597,6 +604,63 @@
             return true;
         }
 
+        @Override
+        public void handOffAnimation(
+                RemoteAnimationTarget[] targets, WindowAnimationState[] states) {
+            mExecutor.execute(() -> {
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                        "[%d] RecentsController.handOffAnimation", mInstanceId);
+
+                if (mTakeoverHandler == null) {
+                    Slog.e(TAG, "Tried to hand off an animation without a valid takeover "
+                            + "handler.");
+                    return;
+                }
+
+                if (targets.length != states.length) {
+                    Slog.e(TAG, "Tried to hand off an animation, but the number of targets "
+                            + "(" + targets.length + ") doesn't match the number of states "
+                            + "(" + states.length + ")");
+                    return;
+                }
+
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                        "[%d] RecentsController.handOffAnimation: got %d states for %d "
+                                + "changes", mInstanceId, states.length, mInfo.getChanges().size());
+                WindowAnimationState[] updatedStates =
+                        new WindowAnimationState[mInfo.getChanges().size()];
+
+                // Ensure that the ordering of animation states is the same as that of  matching
+                // changes in mInfo. prefixOrderIndex is set up in reverse order to that of the
+                // changes, so that's what we use to get to the correct ordering.
+                for (int i = 0; i < targets.length; i++) {
+                    RemoteAnimationTarget target = targets[i];
+                    updatedStates[updatedStates.length - target.prefixOrderIndex] = states[i];
+                }
+
+                Transitions.TransitionFinishCallback finishCB = mFinishCB;
+                // Reset the callback here, so any stray calls that aren't coming from the new
+                // handler are ignored.
+                mFinishCB = null;
+
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                        "[%d] RecentsController.handOffAnimation: calling "
+                                + "takeOverAnimation with %d states", mInstanceId,
+                        updatedStates.length);
+                mTakeoverHandler.takeOverAnimation(
+                        mTransition, mInfo, new SurfaceControl.Transaction(),
+                        wct -> {
+                            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                                    "[%d] RecentsController.handOffAnimation: finish "
+                                            + "callback", mInstanceId);
+                            // Set the callback once again so we can finish correctly.
+                            mFinishCB = finishCB;
+                            finishInner(true /* toHome */, false /* userLeave */,
+                                    null /* finishCb */);
+                        }, updatedStates);
+            });
+        }
+
         /**
          * Updates this controller when a new transition is requested mid-recents transition.
          */
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 fadc970..4c68106 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
@@ -1762,10 +1762,8 @@
     void finishEnterSplitScreen(SurfaceControl.Transaction finishT) {
         ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "finishEnterSplitScreen");
         mSplitLayout.update(finishT, true /* resetImePosition */);
-        mMainStage.getSplitDecorManager().inflate(mContext, mMainStage.mRootLeash,
-                getMainStageBounds());
-        mSideStage.getSplitDecorManager().inflate(mContext, mSideStage.mRootLeash,
-                getSideStageBounds());
+        mMainStage.getSplitDecorManager().inflate(mContext, mMainStage.mRootLeash);
+        mSideStage.getSplitDecorManager().inflate(mContext, mSideStage.mRootLeash);
         setDividerVisibility(true, finishT);
         // Ensure divider surface are re-parented back into the hierarchy at the end of the
         // transition. See Transition#buildFinishTransaction for more detail.
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 f33ab33..f41bca3 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
@@ -218,8 +218,7 @@
             // Inflates split decor view only when the root task is visible.
             if (!ENABLE_SHELL_TRANSITIONS && mRootTaskInfo.isVisible != taskInfo.isVisible) {
                 if (taskInfo.isVisible) {
-                    mSplitDecorManager.inflate(mContext, mRootLeash,
-                            taskInfo.configuration.windowConfiguration.getBounds());
+                    mSplitDecorManager.inflate(mContext, mRootLeash);
                 } else {
                     mSyncQueue.runInSync(t -> mSplitDecorManager.release(t));
                 }
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
index da3aa4a..e552e6c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenWindowCreator.java
@@ -30,7 +30,6 @@
 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;
@@ -54,7 +53,6 @@
 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;
@@ -206,7 +204,6 @@
                 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) {
@@ -427,8 +424,6 @@
 
         private boolean mSetSplashScreen;
         private SplashScreenView mSplashView;
-        private int mSystemBarAppearance;
-        private boolean mDrawsSystemBarBackgrounds;
 
         SplashWindowRecord(IBinder appToken, View decorView,
                 @StartingWindowInfo.StartingWindowType int suggestType) {
@@ -448,19 +443,6 @@
             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();
-        }
-
         @Override
         public boolean removeIfPossible(StartingWindowRemovalInfo info, boolean immediately) {
             if (mRootView == null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java
index 56c0d0e..c886cc9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java
@@ -42,4 +42,7 @@
     public static final String KEY_EXTRA_SHELL_DESKTOP_MODE = "extra_shell_desktop_mode";
     // See IDragAndDrop.aidl
     public static final String KEY_EXTRA_SHELL_DRAG_AND_DROP = "extra_shell_drag_and_drop";
+    // See IRecentsAnimationController.aidl
+    public static final String KEY_EXTRA_SHELL_CAN_HAND_OFF_ANIMATION =
+            "extra_shell_can_hand_off_animation";
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
index 94519a0..69c4167 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/OneShotRemoteHandler.java
@@ -27,6 +27,7 @@
 import android.window.RemoteTransition;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
+import android.window.WindowAnimationState;
 import android.window.WindowContainerTransaction;
 
 import com.android.internal.protolog.common.ProtoLog;
@@ -65,30 +66,9 @@
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Using registered One-shot remote"
                 + " transition %s for (#%d).", mRemote, info.getDebugId());
 
-        final IBinder.DeathRecipient remoteDied = () -> {
-            Log.e(Transitions.TAG, "Remote transition died, finishing");
-            mMainExecutor.execute(
-                    () -> finishCallback.onTransitionFinished(null /* wct */));
-        };
-        IRemoteTransitionFinishedCallback cb = new IRemoteTransitionFinishedCallback.Stub() {
-            @Override
-            public void onTransitionFinished(WindowContainerTransaction wct,
-                    SurfaceControl.Transaction sct) {
-                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
-                        "Finished one-shot remote transition %s for (#%d).", mRemote,
-                        info.getDebugId());
-                if (mRemote.asBinder() != null) {
-                    mRemote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */);
-                }
-                if (sct != null) {
-                    finishTransaction.merge(sct);
-                }
-                mMainExecutor.execute(() -> {
-                    finishCallback.onTransitionFinished(wct);
-                    mRemote = null;
-                });
-            }
-        };
+        final IBinder.DeathRecipient remoteDied = createDeathRecipient(finishCallback);
+        IRemoteTransitionFinishedCallback cb =
+                createFinishedCallback(info, finishTransaction, finishCallback, remoteDied);
         Transitions.setRunningRemoteTransitionDelegate(mRemote.getAppThread());
         try {
             if (mRemote.asBinder() != null) {
@@ -152,6 +132,51 @@
     }
 
     @Override
+    public boolean takeOverAnimation(
+            @NonNull IBinder transition, @NonNull TransitionInfo info,
+            @NonNull SurfaceControl.Transaction transaction,
+            @NonNull Transitions.TransitionFinishCallback finishCallback,
+            @NonNull WindowAnimationState[] states) {
+        if (mTransition != transition) return false;
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "Using registered One-shot "
+                + "remote transition %s to take over (#%d).", mRemote, info.getDebugId());
+
+        final IBinder.DeathRecipient remoteDied = createDeathRecipient(finishCallback);
+        IRemoteTransitionFinishedCallback cb = createFinishedCallback(
+                info, null /* finishTransaction */, finishCallback, remoteDied);
+
+        Transitions.setRunningRemoteTransitionDelegate(mRemote.getAppThread());
+
+        try {
+            if (mRemote.asBinder() != null) {
+                mRemote.asBinder().linkToDeath(remoteDied, 0 /* flags */);
+            }
+
+            // If the remote is actually in the same process, then make a copy of parameters since
+            // remote impls assume that they have to clean-up native references.
+            final SurfaceControl.Transaction remoteStartT =
+                    RemoteTransitionHandler.copyIfLocal(transaction, mRemote.getRemoteTransition());
+            final TransitionInfo remoteInfo =
+                    remoteStartT == transaction ? info : info.localRemoteCopy();
+            mRemote.getRemoteTransition().takeOverAnimation(
+                    transition, remoteInfo, remoteStartT, cb, states);
+
+            // Assume that remote will apply the transaction.
+            transaction.clear();
+            return true;
+        } catch (RemoteException e) {
+            Log.e(Transitions.TAG, "Error running remote transition takeover.", e);
+            if (mRemote.asBinder() != null) {
+                mRemote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */);
+            }
+            finishCallback.onTransitionFinished(null /* wct */);
+            mRemote = null;
+        }
+
+        return false;
+    }
+
+    @Override
     @Nullable
     public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
             @Nullable TransitionRequestInfo request) {
@@ -174,6 +199,41 @@
         }
     }
 
+    private IBinder.DeathRecipient createDeathRecipient(
+            Transitions.TransitionFinishCallback finishCallback) {
+        return () -> {
+            Log.e(Transitions.TAG, "Remote transition died, finishing");
+            mMainExecutor.execute(
+                    () -> finishCallback.onTransitionFinished(null /* wct */));
+        };
+    }
+
+    private IRemoteTransitionFinishedCallback createFinishedCallback(
+            @NonNull TransitionInfo info,
+            @Nullable SurfaceControl.Transaction finishTransaction,
+            @NonNull Transitions.TransitionFinishCallback finishCallback,
+            @NonNull IBinder.DeathRecipient remoteDied) {
+        return new IRemoteTransitionFinishedCallback.Stub() {
+            @Override
+            public void onTransitionFinished(WindowContainerTransaction wct,
+                    SurfaceControl.Transaction sct) {
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
+                        "Finished one-shot remote transition %s for (#%d).", mRemote,
+                        info.getDebugId());
+                if (mRemote.asBinder() != null) {
+                    mRemote.asBinder().unlinkToDeath(remoteDied, 0 /* flags */);
+                }
+                if (finishTransaction != null && sct != null) {
+                    finishTransaction.merge(sct);
+                }
+                mMainExecutor.execute(() -> {
+                    finishCallback.onTransitionFinished(wct);
+                    mRemote = null;
+                });
+            }
+        };
+    }
+
     @Override
     public String toString() {
         return "OneShotRemoteHandler:" + mRemote.getDebugName() + ":"
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 4c4c580..d686046 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
@@ -16,6 +16,8 @@
 
 package com.android.wm.shell.transition;
 
+import static com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.IBinder;
@@ -32,6 +34,7 @@
 import android.window.TransitionFilter;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
+import android.window.WindowAnimationState;
 import android.window.WindowContainerTransaction;
 
 import androidx.annotation.BinderThread;
@@ -41,7 +44,9 @@
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.shared.TransitionUtil;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
  * Handler that deals with RemoteTransitions. It will only request to handle a transition
@@ -58,6 +63,8 @@
     /** Ordered by specificity. Last filters will be checked first */
     private final ArrayList<Pair<TransitionFilter, RemoteTransition>> mFilters =
             new ArrayList<>();
+    private final ArrayList<Pair<TransitionFilter, RemoteTransition>> mTakeoverFilters =
+            new ArrayList<>();
 
     private final ArrayMap<IBinder, RemoteDeathHandler> mDeathHandlers = new ArrayMap<>();
 
@@ -70,14 +77,23 @@
         mFilters.add(new Pair<>(filter, remote));
     }
 
+    void addFilteredForTakeover(TransitionFilter filter, RemoteTransition remote) {
+        handleDeath(remote.asBinder(), null /* finishCallback */);
+        mTakeoverFilters.add(new Pair<>(filter, remote));
+    }
+
     void removeFiltered(RemoteTransition remote) {
         boolean removed = false;
-        for (int i = mFilters.size() - 1; i >= 0; --i) {
-            if (mFilters.get(i).second.asBinder().equals(remote.asBinder())) {
-                mFilters.remove(i);
-                removed = true;
+        for (ArrayList<Pair<TransitionFilter, RemoteTransition>> filters
+                : Arrays.asList(mFilters, mTakeoverFilters)) {
+            for (int i = filters.size() - 1; i >= 0; --i) {
+                if (filters.get(i).second.asBinder().equals(remote.asBinder())) {
+                    filters.remove(i);
+                    removed = true;
+                }
             }
         }
+
         if (removed) {
             unhandleDeath(remote.asBinder(), null /* finishCallback */);
         }
@@ -237,6 +253,47 @@
         }
     }
 
+    @Nullable
+    @Override
+    public Transitions.TransitionHandler getHandlerForTakeover(
+            @NonNull IBinder transition, @NonNull TransitionInfo info) {
+        if (!returnAnimationFrameworkLibrary()) {
+            return null;
+        }
+
+        for (Pair<TransitionFilter, RemoteTransition> registered : mTakeoverFilters) {
+            if (registered.first.matches(info)) {
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                        "Found matching remote to takeover (#%d)", info.getDebugId());
+
+                OneShotRemoteHandler oneShot =
+                        new OneShotRemoteHandler(mMainExecutor, registered.second);
+                oneShot.setTransition(transition);
+                return oneShot;
+            }
+        }
+
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                "No matching remote found to takeover (#%d)", info.getDebugId());
+        return null;
+    }
+
+    @Override
+    public boolean takeOverAnimation(
+            @NonNull IBinder transition, @NonNull TransitionInfo info,
+            @NonNull SurfaceControl.Transaction transaction,
+            @NonNull Transitions.TransitionFinishCallback finishCallback,
+            @NonNull WindowAnimationState[] states) {
+        Transitions.TransitionHandler handler = getHandlerForTakeover(transition, info);
+        if (handler == null) {
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                    "Take over request failed: no matching remote for (#%d)", info.getDebugId());
+            return false;
+        }
+        ((OneShotRemoteHandler) handler).setTransition(transition);
+        return handler.takeOverAnimation(transition, info, transaction, finishCallback, states);
+    }
+
     @Override
     @Nullable
     public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@@ -284,6 +341,34 @@
         }
     }
 
+    void dump(@NonNull PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+
+        pw.println(prefix + "Registered Remotes:");
+        if (mFilters.isEmpty()) {
+            pw.println(innerPrefix + "none");
+        } else {
+            for (Pair<TransitionFilter, RemoteTransition> entry : mFilters) {
+                dumpRemote(pw, innerPrefix, entry.second);
+            }
+        }
+
+        pw.println(prefix + "Registered Takeover Remotes:");
+        if (mTakeoverFilters.isEmpty()) {
+            pw.println(innerPrefix + "none");
+        } else {
+            for (Pair<TransitionFilter, RemoteTransition> entry : mTakeoverFilters) {
+                dumpRemote(pw, innerPrefix, entry.second);
+            }
+        }
+    }
+
+    private void dumpRemote(@NonNull PrintWriter pw, String prefix, RemoteTransition remote) {
+        pw.print(prefix);
+        pw.print(remote.getDebugName());
+        pw.println(" (" + Integer.toHexString(System.identityHashCode(remote)) + ")");
+    }
+
     /** NOTE: binder deaths can alter the filter order */
     private class RemoteDeathHandler implements IBinder.DeathRecipient {
         private final IBinder mRemote;
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 437a00e..9b2922d 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
@@ -35,6 +35,7 @@
 import static android.window.TransitionInfo.FLAG_NO_ANIMATION;
 import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
 
+import static com.android.systemui.shared.Flags.returnAnimationFrameworkLibrary;
 import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
 import static com.android.wm.shell.shared.TransitionUtil.isClosingType;
 import static com.android.wm.shell.shared.TransitionUtil.isOpeningType;
@@ -43,9 +44,11 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityTaskManager;
+import android.app.AppGlobals;
 import android.app.IApplicationThread;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.os.Handler;
 import android.os.IBinder;
@@ -62,6 +65,7 @@
 import android.window.TransitionInfo;
 import android.window.TransitionMetrics;
 import android.window.TransitionRequestInfo;
+import android.window.WindowAnimationState;
 import android.window.WindowContainerTransaction;
 
 import androidx.annotation.BinderThread;
@@ -124,8 +128,7 @@
     static final String TAG = "ShellTransitions";
 
     /** Set to {@code true} to enable shell transitions. */
-    public static final boolean ENABLE_SHELL_TRANSITIONS =
-            SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
+    public static final boolean ENABLE_SHELL_TRANSITIONS = getShellTransitEnabled();
     public static final boolean SHELL_TRANSITIONS_ROTATION = ENABLE_SHELL_TRANSITIONS
             && SystemProperties.getBoolean("persist.wm.debug.shell_transit_rotate", false);
 
@@ -419,12 +422,24 @@
         mHandlers.set(0, handler);
     }
 
-    /** Register a remote transition to be used when `filter` matches an incoming transition */
+    /**
+     * Register a remote transition to be used for all operations except takeovers when `filter`
+     * matches an incoming transition.
+     */
     public void registerRemote(@NonNull TransitionFilter filter,
             @NonNull RemoteTransition remoteTransition) {
         mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
     }
 
+    /**
+     * Register a remote transition to be used for all operations except takeovers when `filter`
+     * matches an incoming transition.
+     */
+    public void registerRemoteForTakeover(@NonNull TransitionFilter filter,
+            @NonNull RemoteTransition remoteTransition) {
+        mRemoteTransitionHandler.addFilteredForTakeover(filter, remoteTransition);
+    }
+
     /** Unregisters a remote transition and all associated filters */
     public void unregisterRemote(@NonNull RemoteTransition remoteTransition) {
         mRemoteTransitionHandler.removeFiltered(remoteTransition);
@@ -1187,6 +1202,29 @@
     }
 
     /**
+     * Checks whether a handler exists capable of taking over the given transition, and returns it.
+     * Otherwise it returns null.
+     */
+    @Nullable
+    public TransitionHandler getHandlerForTakeover(
+            @NonNull IBinder transition, @NonNull TransitionInfo info) {
+        if (!returnAnimationFrameworkLibrary()) {
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+                    "Trying to get a handler for takeover but the flag is disabled");
+            return null;
+        }
+
+        for (TransitionHandler handler : mHandlers) {
+            TransitionHandler candidate = handler.getHandlerForTakeover(transition, info);
+            if (candidate != null) {
+                return candidate;
+            }
+        }
+
+        return null;
+    }
+
+    /**
      * Finish running animations (almost) immediately when a SLEEP transition comes in. We use this
      * as both a way to reduce unnecessary work (animations not visible while screen off) and as a
      * failsafe to unblock "stuck" animations (in particular remote animations).
@@ -1328,6 +1366,49 @@
                 @NonNull TransitionFinishCallback finishCallback) { }
 
         /**
+         * Checks whether this handler is capable of taking over a transition matching `info`.
+         * {@link TransitionHandler#takeOverAnimation(IBinder, TransitionInfo,
+         * SurfaceControl.Transaction, TransitionFinishCallback, WindowAnimationState[])} is
+         * guaranteed to succeed if called on the handler returned by this method.
+         *
+         * Note that the handler returned by this method can either be itself, or a different one
+         * selected by this handler to take care of the transition on its behalf.
+         *
+         * @param transition The transition that should be taken over.
+         * @param info Information about the transition to be taken over.
+         * @return A handler capable of taking over a matching transition, or null.
+         */
+        @Nullable
+        default TransitionHandler getHandlerForTakeover(
+                @NonNull IBinder transition, @NonNull TransitionInfo info) {
+            return null;
+        }
+
+        /**
+         * Attempt to take over a running transition. This must succeed if this handler was returned
+         * by {@link TransitionHandler#getHandlerForTakeover(IBinder, TransitionInfo)}.
+         *
+         * @param transition The transition that should be taken over.
+         * @param info Information about the what is changing in the transition.
+         * @param transaction Contains surface changes that resulted from the transition. Any
+         *                    additional changes should be added to this transaction and committed
+         *                    inside this method.
+         * @param finishCallback Call this at the end of the animation, if the take-over succeeds.
+         *                       Note that this will be called instead of the callback originally
+         *                       passed to startAnimation(), so the caller should make sure all
+         *                       necessary cleanup happens here. This MUST be called on main thread.
+         * @param states The animation states of the transition's window at the time this method was
+         *               called.
+         * @return true if the transition was taken over, false if not.
+         */
+        default boolean takeOverAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
+                @NonNull SurfaceControl.Transaction transaction,
+                @NonNull TransitionFinishCallback finishCallback,
+                @NonNull WindowAnimationState[] states) {
+            return false;
+        }
+
+        /**
          * Potentially handles a startTransition request.
          *
          * @param transition The transition whose start is being requested.
@@ -1432,16 +1513,21 @@
         @Override
         public void registerRemote(@NonNull TransitionFilter filter,
                 @NonNull RemoteTransition remoteTransition) {
-            mMainExecutor.execute(() -> {
-                mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
-            });
+            mMainExecutor.execute(
+                    () -> mRemoteTransitionHandler.addFiltered(filter, remoteTransition));
+        }
+
+        @Override
+        public void registerRemoteForTakeover(@NonNull TransitionFilter filter,
+                @NonNull RemoteTransition remoteTransition) {
+            mMainExecutor.execute(() -> mRemoteTransitionHandler.addFilteredForTakeover(
+                    filter, remoteTransition));
         }
 
         @Override
         public void unregisterRemote(@NonNull RemoteTransition remoteTransition) {
-            mMainExecutor.execute(() -> {
-                mRemoteTransitionHandler.removeFiltered(remoteTransition);
-            });
+            mMainExecutor.execute(
+                    () -> mRemoteTransitionHandler.removeFiltered(remoteTransition));
         }
     }
 
@@ -1470,17 +1556,23 @@
         public void registerRemote(@NonNull TransitionFilter filter,
                 @NonNull RemoteTransition remoteTransition) {
             executeRemoteCallWithTaskPermission(mTransitions, "registerRemote",
-                    (transitions) -> {
-                        transitions.mRemoteTransitionHandler.addFiltered(filter, remoteTransition);
-                    });
+                    (transitions) -> transitions.mRemoteTransitionHandler.addFiltered(
+                            filter, remoteTransition));
+        }
+
+        @Override
+        public void registerRemoteForTakeover(@NonNull TransitionFilter filter,
+                @NonNull RemoteTransition remoteTransition) {
+            executeRemoteCallWithTaskPermission(mTransitions, "registerRemoteForTakeover",
+                    (transitions) -> transitions.mRemoteTransitionHandler.addFilteredForTakeover(
+                            filter, remoteTransition));
         }
 
         @Override
         public void unregisterRemote(@NonNull RemoteTransition remoteTransition) {
             executeRemoteCallWithTaskPermission(mTransitions, "unregisterRemote",
-                    (transitions) -> {
-                        transitions.mRemoteTransitionHandler.removeFiltered(remoteTransition);
-                    });
+                    (transitions) ->
+                            transitions.mRemoteTransitionHandler.removeFiltered(remoteTransition));
         }
 
         @Override
@@ -1565,6 +1657,8 @@
             pw.println(" (" + Integer.toHexString(System.identityHashCode(handler)) + ")");
         }
 
+        mRemoteTransitionHandler.dump(pw, prefix);
+
         pw.println(prefix + "Observers:");
         for (TransitionObserver observer : mObservers) {
             pw.print(innerPrefix);
@@ -1617,4 +1711,16 @@
             }
         }
     }
+
+    private static boolean getShellTransitEnabled() {
+        try {
+            if (AppGlobals.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_AUTOMOTIVE, 0)) {
+                return SystemProperties.getBoolean("persist.wm.debug.shell_transit", true);
+            }
+        } catch (RemoteException re) {
+            Log.w(TAG, "Error getting system features");
+        }
+        return true;
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index 43fd32b..6671391 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -200,7 +200,6 @@
         mRelayoutParams.mShadowRadiusId = shadowRadiusID;
         mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
         mRelayoutParams.mSetTaskPositionAndCrop = setTaskCropAndPosition;
-        mRelayoutParams.mAllowCaptionInputFallthrough = false;
 
         relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
         // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
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 6a9d17f..922c55f 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
@@ -1037,7 +1037,6 @@
                         mSyncQueue,
                         mRootTaskDisplayAreaOrganizer);
         mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
-        windowDecoration.createResizeVeil();
 
         final DragPositioningCallback dragPositioningCallback;
         if (!DesktopModeStatus.isVeiledResizeEnabled()) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index da1699c..cb6495c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -44,6 +44,7 @@
 import android.graphics.Region;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
+import android.os.Trace;
 import android.util.Log;
 import android.util.Size;
 import android.view.Choreographer;
@@ -51,6 +52,7 @@
 import android.view.SurfaceControl;
 import android.view.View;
 import android.view.ViewConfiguration;
+import android.view.WindowManager;
 import android.widget.ImageButton;
 import android.window.WindowContainerTransaction;
 
@@ -107,8 +109,6 @@
     private MaximizeMenu mMaximizeMenu;
 
     private ResizeVeil mResizeVeil;
-
-    private Drawable mAppIconDrawable;
     private Bitmap mAppIconBitmap;
     private CharSequence mAppName;
 
@@ -160,7 +160,9 @@
         mSyncQueue = syncQueue;
         mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
 
+        Trace.beginSection("DesktopModeWindowDecoration#loadAppInfo");
         loadAppInfo();
+        Trace.endSection();
     }
 
     void setCaptionListeners(
@@ -206,6 +208,7 @@
     void relayout(ActivityManager.RunningTaskInfo taskInfo,
             SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
             boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop) {
+        Trace.beginSection("DesktopModeWindowDecoration#relayout");
         if (isHandleMenuActive()) {
             mHandleMenu.relayout(startT);
         }
@@ -217,16 +220,22 @@
         final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
         final WindowContainerTransaction wct = new WindowContainerTransaction();
 
+        Trace.beginSection("DesktopModeWindowDecoration#relayout-inner");
         relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
+        Trace.endSection();
         // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
 
+        Trace.beginSection("DesktopModeWindowDecoration#relayout-applyWCT");
         mTaskOrganizer.applyTransaction(wct);
+        Trace.endSection();
 
         if (mResult.mRootView == null) {
             // This means something blocks the window decor from showing, e.g. the task is hidden.
             // Nothing is set up in this case including the decoration surface.
+            Trace.endSection(); // DesktopModeWindowDecoration#relayout
             return;
         }
+
         if (oldRootView != mResult.mRootView) {
             if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_focused_window_decor) {
                 mWindowDecorViewHolder = new DesktopModeFocusedWindowDecorationViewHolder(
@@ -254,7 +263,9 @@
                 throw new IllegalArgumentException("Unexpected layout resource id");
             }
         }
+        Trace.beginSection("DesktopModeWindowDecoration#relayout-binding");
         mWindowDecorViewHolder.bindData(mTaskInfo);
+        Trace.endSection();
 
         if (!mTaskInfo.isFocused) {
             closeHandleMenu();
@@ -270,11 +281,13 @@
                 updateExclusionRegion();
             }
             closeDragResizeListener();
+            Trace.endSection(); // DesktopModeWindowDecoration#relayout
             return;
         }
 
         if (oldDecorationSurface != mDecorationContainerSurface || mDragResizeListener == null) {
             closeDragResizeListener();
+            Trace.beginSection("DesktopModeWindowDecoration#relayout-DragResizeInputListener");
             mDragResizeListener = new DragResizeInputListener(
                     mContext,
                     mHandler,
@@ -285,6 +298,7 @@
                     mSurfaceControlBuilderSupplier,
                     mSurfaceControlTransactionSupplier,
                     mDisplayController);
+            Trace.endSection();
         }
 
         final int touchSlop = ViewConfiguration.get(mResult.mRootView.getContext())
@@ -309,6 +323,7 @@
                 mMaximizeMenu.positionMenu(calculateMaximizeMenuPosition(), startT);
             }
         }
+        Trace.endSection(); // DesktopModeWindowDecoration#relayout
     }
 
     @VisibleForTesting
@@ -326,11 +341,12 @@
         relayoutParams.mCaptionWidthId = getCaptionWidthId(relayoutParams.mLayoutResId);
 
         if (captionLayoutId == R.layout.desktop_mode_app_controls_window_decor) {
-            // If the app is requesting to customize the caption bar, allow input to fall through
-            // to the windows below so that the app can respond to input events on their custom
-            // content.
-            relayoutParams.mAllowCaptionInputFallthrough =
-                    TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo);
+            if (TaskInfoKt.isTransparentCaptionBarAppearance(taskInfo)) {
+                // If the app is requesting to customize the caption bar, allow input to fall
+                // through to the windows below so that the app can respond to input events on
+                // their custom content.
+                relayoutParams.mInputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_SPY;
+            }
             // Report occluding elements as bounding rects to the insets system so that apps can
             // draw in the empty space in the center:
             //   First, the "app chip" section of the caption bar (+ some extra margins).
@@ -345,6 +361,11 @@
             controlsElement.mWidthResId = R.dimen.desktop_mode_customizable_caption_margin_end;
             controlsElement.mAlignment = RelayoutParams.OccludingCaptionElement.Alignment.END;
             relayoutParams.mOccludingCaptionElements.add(controlsElement);
+        } else if (captionLayoutId == R.layout.desktop_mode_focused_window_decor) {
+            // The focused decor (fullscreen/split) does not need to handle input because input in
+            // the App Handle is handled by the InputMonitor in DesktopModeWindowDecorViewModel.
+            relayoutParams.mInputFeatures
+                    |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
         }
         if (DesktopModeStatus.useWindowShadow(/* isFocusedWindow= */ taskInfo.isFocused)) {
             relayoutParams.mShadowRadiusId = taskInfo.isFocused
@@ -444,12 +465,12 @@
         }
         PackageManager pm = mContext.getApplicationContext().getPackageManager();
         final IconProvider provider = new IconProvider(mContext);
-        mAppIconDrawable = provider.getIcon(activityInfo);
+        final Drawable appIconDrawable = provider.getIcon(activityInfo);
         final Resources resources = mContext.getResources();
         final BaseIconFactory factory = new BaseIconFactory(mContext,
                 resources.getDisplayMetrics().densityDpi,
                 resources.getDimensionPixelSize(R.dimen.desktop_mode_caption_icon_radius));
-        mAppIconBitmap = factory.createScaledBitmap(mAppIconDrawable, MODE_DEFAULT);
+        mAppIconBitmap = factory.createScaledBitmap(appIconDrawable, MODE_DEFAULT);
         final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
         mAppName = pm.getApplicationLabel(applicationInfo);
     }
@@ -466,8 +487,9 @@
      * Create the resize veil for this task. Note the veil's visibility is View.GONE by default
      * until a resize event calls showResizeVeil below.
      */
-    void createResizeVeil() {
-        mResizeVeil = new ResizeVeil(mContext, mDisplayController, mAppIconDrawable, mTaskInfo,
+    private void createResizeVeilIfNeeded() {
+        if (mResizeVeil != null) return;
+        mResizeVeil = new ResizeVeil(mContext, mDisplayController, mAppIconBitmap, mTaskInfo,
                 mTaskSurface, mSurfaceControlTransactionSupplier);
     }
 
@@ -475,6 +497,7 @@
      * Show the resize veil.
      */
     public void showResizeVeil(Rect taskBounds) {
+        createResizeVeilIfNeeded();
         mResizeVeil.showVeil(mTaskSurface, taskBounds);
     }
 
@@ -482,6 +505,7 @@
      * Show the resize veil.
      */
     public void showResizeVeil(SurfaceControl.Transaction tx, Rect taskBounds) {
+        createResizeVeilIfNeeded();
         mResizeVeil.showVeil(tx, mTaskSurface, taskBounds, false /* fadeIn */);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
index 2c4092a..93e2a21 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/ResizeVeil.java
@@ -24,11 +24,12 @@
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
 import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
+import android.os.Trace;
 import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.SurfaceControl;
@@ -64,7 +65,7 @@
     private final SurfaceControlBuilderFactory mSurfaceControlBuilderFactory;
     private final WindowDecoration.SurfaceControlViewHostFactory mSurfaceControlViewHostFactory;
     private final SurfaceSession mSurfaceSession = new SurfaceSession();
-    private final Drawable mAppIcon;
+    private final Bitmap mAppIcon;
     private ImageView mIconView;
     private int mIconSize;
     private SurfaceControl mParentSurface;
@@ -97,7 +98,7 @@
 
     public ResizeVeil(Context context,
             @NonNull DisplayController displayController,
-            Drawable appIcon, RunningTaskInfo taskInfo,
+            Bitmap appIcon, RunningTaskInfo taskInfo,
             SurfaceControl taskSurface,
             Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier) {
         this(context,
@@ -112,7 +113,7 @@
 
     public ResizeVeil(Context context,
             @NonNull DisplayController displayController,
-            Drawable appIcon, RunningTaskInfo taskInfo,
+            Bitmap appIcon, RunningTaskInfo taskInfo,
             SurfaceControl taskSurface,
             Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
             SurfaceControlBuilderFactory surfaceControlBuilderFactory,
@@ -135,6 +136,7 @@
             // Display may not be available yet, skip this until then.
             return;
         }
+        Trace.beginSection("ResizeVeil#setupResizeVeil");
         mVeilSurface = mSurfaceControlBuilderFactory
                 .create("Resize veil of Task=" + mTaskInfo.taskId)
                 .setContainerLayer()
@@ -162,7 +164,7 @@
         final View root = LayoutInflater.from(mContext)
                 .inflate(R.layout.desktop_mode_resize_veil, null /* root */);
         mIconView = root.findViewById(R.id.veil_application_icon);
-        mIconView.setImageDrawable(mAppIcon);
+        mIconView.setImageBitmap(mAppIcon);
 
         final WindowManager.LayoutParams lp =
                 new WindowManager.LayoutParams(
@@ -179,6 +181,7 @@
 
         mViewHost = mSurfaceControlViewHostFactory.create(mContext, mDisplay, wwm, "ResizeVeil");
         mViewHost.setView(root, lp);
+        Trace.endSection();
     }
 
     private boolean obtainDisplayOrRegisterListener() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 36da1ac..54656ff 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -33,6 +33,7 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Binder;
+import android.os.Trace;
 import android.view.Display;
 import android.view.InsetsSource;
 import android.view.InsetsState;
@@ -311,7 +312,7 @@
                 boundingRects = null;
             } else {
                 // The customizable region can at most be equal to the caption bar.
-                if (params.mAllowCaptionInputFallthrough) {
+                if (params.hasInputFeatureSpy()) {
                     outResult.mCustomizableCaptionRegion.set(mCaptionInsetsRect);
                 }
                 boundingRects = new Rect[numOfElements];
@@ -324,7 +325,7 @@
                             calculateBoundingRect(element, elementWidthPx, mCaptionInsetsRect);
                     // Subtract the regions used by the caption elements, the rest is
                     // customizable.
-                    if (params.mAllowCaptionInputFallthrough) {
+                    if (params.hasInputFeatureSpy()) {
                         outResult.mCustomizableCaptionRegion.op(boundingRects[i],
                                 Region.Op.DIFFERENCE);
                     }
@@ -378,6 +379,7 @@
             startT.unsetColor(mTaskSurface);
         }
 
+        Trace.beginSection("CaptionViewHostLayout");
         if (mCaptionWindowManager == null) {
             // Put caption under a container surface because ViewRootImpl sets the destination frame
             // of windowless window layers and BLASTBufferQueue#update() doesn't support offset.
@@ -394,11 +396,7 @@
                         WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
         lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
         lp.setTrustedOverlay();
-        if (params.mAllowCaptionInputFallthrough) {
-            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_SPY;
-        } else {
-            lp.inputFeatures &= ~WindowManager.LayoutParams.INPUT_FEATURE_SPY;
-        }
+        lp.inputFeatures = params.mInputFeatures;
         if (mViewHost == null) {
             mViewHost = mSurfaceControlViewHostFactory.create(mDecorWindowContext, mDisplay,
                     mCaptionWindowManager);
@@ -412,6 +410,7 @@
             }
             mViewHost.relayout(lp);
         }
+        Trace.endSection(); // CaptionViewHostLayout
     }
 
     private Rect calculateBoundingRect(@NonNull OccludingCaptionElement element,
@@ -605,7 +604,7 @@
         int mCaptionHeightId;
         int mCaptionWidthId;
         final List<OccludingCaptionElement> mOccludingCaptionElements = new ArrayList<>();
-        boolean mAllowCaptionInputFallthrough;
+        int mInputFeatures;
 
         int mShadowRadiusId;
         int mCornerRadius;
@@ -620,7 +619,7 @@
             mCaptionHeightId = Resources.ID_NULL;
             mCaptionWidthId = Resources.ID_NULL;
             mOccludingCaptionElements.clear();
-            mAllowCaptionInputFallthrough = false;
+            mInputFeatures = 0;
 
             mShadowRadiusId = Resources.ID_NULL;
             mCornerRadius = 0;
@@ -630,6 +629,10 @@
             mWindowDecorConfig = null;
         }
 
+        boolean hasInputFeatureSpy() {
+            return (mInputFeatures & WindowManager.LayoutParams.INPUT_FEATURE_SPY) != 0;
+        }
+
         /**
          * Describes elements within the caption bar that could occlude app content, and should be
          * sent as bounding rectangles to the insets system.
diff --git a/libs/WindowManager/Shell/tests/OWNERS b/libs/WindowManager/Shell/tests/OWNERS
index d718e15..0f24bb5 100644
--- a/libs/WindowManager/Shell/tests/OWNERS
+++ b/libs/WindowManager/Shell/tests/OWNERS
@@ -12,3 +12,4 @@
 nmusgrave@google.com
 pbdr@google.com
 tkachenkoi@google.com
+mpodolian@google.com
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 65169e3..f99b4b2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -354,6 +354,7 @@
         // Verify that we prevent any interaction with the animator callback in case a new gesture
         // starts while the current back animation has not ended, instead the gesture is queued
         triggerBackGesture();
+        verify(mAnimatorCallback).setTriggerBack(eq(true));
         verifyNoMoreInteractions(mAnimatorCallback);
 
         // Finish previous back navigation.
@@ -394,6 +395,7 @@
         // starts while the current back animation has not ended, instead the gesture is queued
         triggerBackGesture();
         releaseBackGesture();
+        verify(mAnimatorCallback).setTriggerBack(eq(true));
         verifyNoMoreInteractions(mAnimatorCallback);
 
         // Finish previous back navigation.
@@ -532,7 +534,7 @@
     }
 
     @Test
-    public void callbackShouldDeliverProgress() throws RemoteException {
+    public void appCallback_receivesStartAndInvoke() throws RemoteException {
         registerAnimation(BackNavigationInfo.TYPE_RETURN_TO_HOME);
 
         final int type = BackNavigationInfo.TYPE_CALLBACK;
@@ -551,8 +553,9 @@
         assertTrue("TriggerBack should have been true", result.mTriggerBack);
 
         verify(mAppCallback, times(1)).onBackStarted(any());
-        verify(mAppCallback, times(1)).onBackProgressed(any());
         verify(mAppCallback, times(1)).onBackInvoked();
+        // Progress events should be generated from the app process.
+        verify(mAppCallback, never()).onBackProgressed(any());
 
         verify(mAnimatorCallback, never()).onBackStarted(any());
         verify(mAnimatorCallback, never()).onBackProgressed(any());
@@ -639,7 +642,7 @@
      */
     private void doStartEvents(int startX, int moveX) {
         doMotionEvent(MotionEvent.ACTION_DOWN, startX);
-        mController.onPilferPointers();
+        mController.onThresholdCrossed();
         doMotionEvent(MotionEvent.ACTION_MOVE, moveX);
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomizeActivityAnimationTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomizeActivityAnimationTest.java
index cebbbd8..158d640 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomizeActivityAnimationTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/CustomizeActivityAnimationTest.java
@@ -96,7 +96,7 @@
                 .loadAnimation(any(), eq(true));
 
         mCustomizeActivityAnimation.prepareNextAnimation(
-                new BackNavigationInfo.CustomAnimationInfo("TestPackage"));
+                new BackNavigationInfo.CustomAnimationInfo("TestPackage"), 0);
         final RemoteAnimationTarget close = createAnimationTarget(false);
         final RemoteAnimationTarget open = createAnimationTarget(true);
         // start animation with remote animation targets
@@ -129,7 +129,7 @@
                 .loadAnimation(any(), eq(true));
 
         mCustomizeActivityAnimation.prepareNextAnimation(
-                new BackNavigationInfo.CustomAnimationInfo("TestPackage"));
+                new BackNavigationInfo.CustomAnimationInfo("TestPackage"), 0);
         final RemoteAnimationTarget close = createAnimationTarget(false);
         final RemoteAnimationTarget open = createAnimationTarget(true);
         // start animation with remote animation targets
@@ -155,7 +155,7 @@
     @Test
     public void receiveFinishWithoutAnimationAfterInvoke() throws InterruptedException {
         mCustomizeActivityAnimation.prepareNextAnimation(
-                new BackNavigationInfo.CustomAnimationInfo("TestPackage"));
+                new BackNavigationInfo.CustomAnimationInfo("TestPackage"), 0);
         // start animation without any remote animation targets
         final CountDownLatch finishCalled = new CountDownLatch(1);
         final Runnable finishCallback = finishCalled::countDown;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
index 2366917..964d86e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/ShellTransitionTests.java
@@ -73,6 +73,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.RemoteException;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.util.ArraySet;
 import android.util.Pair;
 import android.view.IRecentsAnimationRunner;
@@ -87,6 +88,7 @@
 import android.window.TransitionFilter;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
+import android.window.WindowAnimationState;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
@@ -98,6 +100,7 @@
 
 import com.android.internal.R;
 import com.android.internal.policy.TransitionAnimation;
+import com.android.systemui.shared.Flags;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.ShellTestCase;
@@ -114,6 +117,7 @@
 import com.android.wm.shell.util.StubTransaction;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Answers;
@@ -141,6 +145,9 @@
     private final TestTransitionHandler mDefaultHandler = new TestTransitionHandler();
     private final Handler mMainHandler = new Handler(Looper.getMainLooper());
 
+    @Rule
+    public final SetFlagsRule setFlagsRule = new SetFlagsRule();
+
     @Before
     public void setUp() {
         doAnswer(invocation -> new Binder())
@@ -475,11 +482,97 @@
     }
 
     @Test
+    public void testRegisteredRemoteTransitionTakeover() {
+        Transitions transitions = createTestTransitions();
+        transitions.replaceDefaultHandlerForTest(mDefaultHandler);
+
+        IRemoteTransition testRemote = new RemoteTransitionStub() {
+            @Override
+            public void startAnimation(IBinder token, TransitionInfo info,
+                    SurfaceControl.Transaction t,
+                    IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {
+                final Transitions.TransitionHandler takeoverHandler =
+                        transitions.getHandlerForTakeover(token, info);
+
+                if (takeoverHandler == null) {
+                    finishCallback.onTransitionFinished(null /* wct */, null /* sct */);
+                    return;
+                }
+
+                takeoverHandler.takeOverAnimation(token, info, new SurfaceControl.Transaction(),
+                        wct -> {
+                            try {
+                                finishCallback.onTransitionFinished(wct, null /* sct */);
+                            } catch (RemoteException e) {
+                                // Fail
+                            }
+                        }, new WindowAnimationState[info.getChanges().size()]);
+            }
+        };
+        final boolean[] takeoverRemoteCalled = new boolean[]{false};
+        IRemoteTransition testTakeoverRemote = new RemoteTransitionStub() {
+            @Override
+            public void startAnimation(IBinder token, TransitionInfo info,
+                    SurfaceControl.Transaction t,
+                    IRemoteTransitionFinishedCallback finishCallback) {}
+
+            @Override
+            public void takeOverAnimation(IBinder transition, TransitionInfo info,
+                    SurfaceControl.Transaction startTransaction,
+                    IRemoteTransitionFinishedCallback finishCallback, WindowAnimationState[] states)
+                    throws RemoteException {
+                takeoverRemoteCalled[0] = true;
+                finishCallback.onTransitionFinished(null /* wct */, null /* sct */);
+            }
+        };
+
+        TransitionFilter filter = new TransitionFilter();
+        filter.mRequirements =
+                new TransitionFilter.Requirement[]{new TransitionFilter.Requirement()};
+        filter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
+
+        transitions.registerRemote(filter, new RemoteTransition(testRemote, "Test"));
+        transitions.registerRemoteForTakeover(
+                filter, new RemoteTransition(testTakeoverRemote, "Test"));
+        mMainExecutor.flushAll();
+
+        // Takeover shouldn't happen when the flag is disabled.
+        setFlagsRule.disableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY);
+        IBinder transitToken = new Binder();
+        transitions.requestStartTransition(transitToken,
+                new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+        TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN)
+                .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+        transitions.onTransitionReady(transitToken, info, new StubTransaction(),
+                new StubTransaction());
+        assertEquals(0, mDefaultHandler.activeCount());
+        assertFalse(takeoverRemoteCalled[0]);
+        mDefaultHandler.finishAll();
+        mMainExecutor.flushAll();
+        verify(mOrganizer, times(1)).finishTransition(eq(transitToken), any());
+
+        // Takeover should happen when the flag is enabled.
+        setFlagsRule.enableFlags(Flags.FLAG_RETURN_ANIMATION_FRAMEWORK_LIBRARY);
+        transitions.requestStartTransition(transitToken,
+                new TransitionRequestInfo(TRANSIT_OPEN, null /* trigger */, null /* remote */));
+        info = new TransitionInfoBuilder(TRANSIT_OPEN)
+                .addChange(TRANSIT_OPEN).addChange(TRANSIT_CLOSE).build();
+        transitions.onTransitionReady(transitToken, info, new StubTransaction(),
+                new StubTransaction());
+        assertEquals(0, mDefaultHandler.activeCount());
+        assertTrue(takeoverRemoteCalled[0]);
+        mDefaultHandler.finishAll();
+        mMainExecutor.flushAll();
+        verify(mOrganizer, times(2)).finishTransition(eq(transitToken), any());
+    }
+
+    @Test
     public void testOneShotRemoteHandler() {
         Transitions transitions = createTestTransitions();
         transitions.replaceDefaultHandlerForTest(mDefaultHandler);
 
         final boolean[] remoteCalled = new boolean[]{false};
+        final boolean[] takeoverRemoteCalled = new boolean[]{false};
         final WindowContainerTransaction remoteFinishWCT = new WindowContainerTransaction();
         IRemoteTransition testRemote = new RemoteTransitionStub() {
             @Override
@@ -489,12 +582,22 @@
                 remoteCalled[0] = true;
                 finishCallback.onTransitionFinished(remoteFinishWCT, null /* sct */);
             }
+
+            @Override
+            public void takeOverAnimation(IBinder transition, TransitionInfo info,
+                    SurfaceControl.Transaction startTransaction,
+                    IRemoteTransitionFinishedCallback finishCallback, WindowAnimationState[] states)
+                    throws RemoteException {
+                takeoverRemoteCalled[0] = true;
+                finishCallback.onTransitionFinished(remoteFinishWCT, null /* sct */);
+            }
         };
 
         final int transitType = TRANSIT_FIRST_CUSTOM + 1;
 
         OneShotRemoteHandler oneShot = new OneShotRemoteHandler(mMainExecutor,
                 new RemoteTransition(testRemote, "Test"));
+
         // Verify that it responds to the remote but not other things.
         IBinder transitToken = new Binder();
         assertNotNull(oneShot.handleRequest(transitToken,
@@ -505,6 +608,7 @@
 
         Transitions.TransitionFinishCallback testFinish =
                 mock(Transitions.TransitionFinishCallback.class);
+
         // Verify that it responds to animation properly
         oneShot.setTransition(transitToken);
         IBinder anotherToken = new Binder();
@@ -514,6 +618,16 @@
         assertTrue(oneShot.startAnimation(transitToken, new TransitionInfo(transitType, 0),
                 new StubTransaction(), new StubTransaction(),
                 testFinish));
+        assertTrue(remoteCalled[0]);
+
+        // Verify that it handles takeovers properly
+        IBinder newToken = new Binder();
+        oneShot.setTransition(newToken);
+        assertFalse(oneShot.takeOverAnimation(transitToken, new TransitionInfo(transitType, 0),
+                new StubTransaction(), testFinish, new WindowAnimationState[0]));
+        assertTrue(oneShot.takeOverAnimation(newToken, new TransitionInfo(transitType, 0),
+                new StubTransaction(), testFinish, new WindowAnimationState[0]));
+        assertTrue(takeoverRemoteCalled[0]);
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index f9b5882..608f74b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -18,6 +18,7 @@
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.view.WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -44,6 +45,7 @@
 import android.view.Display;
 import android.view.SurfaceControl;
 import android.view.SurfaceControlViewHost;
+import android.view.WindowManager;
 import android.window.WindowContainerTransaction;
 
 import androidx.test.filters.SmallTest;
@@ -187,7 +189,7 @@
                 /* applyStartTransactionOnDraw= */ true,
                 /* shouldSetTaskPositionAndCrop */ false);
 
-        assertThat(relayoutParams.mAllowCaptionInputFallthrough).isTrue();
+        assertThat(relayoutParams.hasInputFeatureSpy()).isTrue();
     }
 
     @Test
@@ -204,7 +206,7 @@
                 /* applyStartTransactionOnDraw= */ true,
                 /* shouldSetTaskPositionAndCrop */ false);
 
-        assertThat(relayoutParams.mAllowCaptionInputFallthrough).isFalse();
+        assertThat(relayoutParams.hasInputFeatureSpy()).isFalse();
     }
 
     @Test
@@ -220,7 +222,55 @@
                 /* applyStartTransactionOnDraw= */ true,
                 /* shouldSetTaskPositionAndCrop */ false);
 
-        assertThat(relayoutParams.mAllowCaptionInputFallthrough).isFalse();
+        assertThat(relayoutParams.hasInputFeatureSpy()).isFalse();
+    }
+
+    @Test
+    public void updateRelayoutParams_freeform_inputChannelNeeded() {
+        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        final RelayoutParams relayoutParams = new RelayoutParams();
+
+        DesktopModeWindowDecoration.updateRelayoutParams(
+                relayoutParams,
+                mTestableContext,
+                taskInfo,
+                /* applyStartTransactionOnDraw= */ true,
+                /* shouldSetTaskPositionAndCrop */ false);
+
+        assertThat(hasNoInputChannelFeature(relayoutParams)).isFalse();
+    }
+
+    @Test
+    public void updateRelayoutParams_fullscreen_inputChannelNotNeeded() {
+        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        final RelayoutParams relayoutParams = new RelayoutParams();
+
+        DesktopModeWindowDecoration.updateRelayoutParams(
+                relayoutParams,
+                mTestableContext,
+                taskInfo,
+                /* applyStartTransactionOnDraw= */ true,
+                /* shouldSetTaskPositionAndCrop */ false);
+
+        assertThat(hasNoInputChannelFeature(relayoutParams)).isTrue();
+    }
+
+    @Test
+    public void updateRelayoutParams_multiwindow_inputChannelNotNeeded() {
+        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
+        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+        final RelayoutParams relayoutParams = new RelayoutParams();
+
+        DesktopModeWindowDecoration.updateRelayoutParams(
+                relayoutParams,
+                mTestableContext,
+                taskInfo,
+                /* applyStartTransactionOnDraw= */ true,
+                /* shouldSetTaskPositionAndCrop */ false);
+
+        assertThat(hasNoInputChannelFeature(relayoutParams)).isTrue();
     }
 
     private void fillRoundedCornersResources(int fillValue) {
@@ -268,4 +318,9 @@
         return taskInfo;
 
     }
+
+    private static boolean hasNoInputChannelFeature(RelayoutParams params) {
+        return (params.mInputFeatures & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL)
+                != 0;
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
index 847c2dd..8742591 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/ResizeVeilTest.kt
@@ -15,8 +15,8 @@
  */
 package com.android.wm.shell.windowdecor
 
+import android.graphics.Bitmap
 import android.graphics.Rect
-import android.graphics.drawable.Drawable
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.view.Display
@@ -60,7 +60,7 @@
     @Mock
     private lateinit var mockDisplayController: DisplayController
     @Mock
-    private lateinit var mockAppIcon: Drawable
+    private lateinit var mockAppIcon: Bitmap
     @Mock
     private lateinit var mockDisplay: Display
     @Mock
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
index a9f4492..48ac1e5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/VeiledResizeTaskPositionerTest.kt
@@ -197,7 +197,7 @@
         rectAfterEnd.top += 20
         rectAfterEnd.bottom += 20
 
-        verify(mockDesktopWindowDecoration, never()).createResizeVeil()
+        verify(mockDesktopWindowDecoration, never()).showResizeVeil(any())
         verify(mockDesktopWindowDecoration, never()).hideResizeVeil()
         verify(mockTransitions).startTransition(eq(TRANSIT_CHANGE), argThat { wct ->
             return@argThat wct.changes.any { (token, change) ->
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index a8e8547..0f29613 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -322,11 +322,16 @@
         return false;
     }
 
-    err = native_window_set_buffer_count(window, windowInfo.bufferCount);
-    if (err != 0) {
-        ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffer_count(%zu) failed: %s (%d)",
-              windowInfo.bufferCount, strerror(-err), err);
-        return false;
+    // If bufferCount == 1 then we're in shared buffer mode and we cannot actually call
+    // set_buffer_count, it'll just fail.
+    if (windowInfo.bufferCount > 1) {
+        err = native_window_set_buffer_count(window, windowInfo.bufferCount);
+        if (err != 0) {
+            ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffer_count(%zu) failed: %s "
+                  "(%d)",
+                  windowInfo.bufferCount, strerror(-err), err);
+            return false;
+        }
     }
 
     err = native_window_set_usage(window, windowInfo.windowUsageFlags);
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index ffd6e16..554fe5e 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -1005,7 +1005,6 @@
      *     RoutingController#wasTransferInitiatedBySelf()}.
      * @hide
      */
-    @FlaggedApi(FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES)
     public void transfer(
             @NonNull RoutingController controller,
             @NonNull MediaRoute2Info route,
diff --git a/nfc/jarjar-rules.txt b/nfc/jarjar-rules.txt
index 99ae144..63a6a58 100644
--- a/nfc/jarjar-rules.txt
+++ b/nfc/jarjar-rules.txt
@@ -27,9 +27,8 @@
 rule android.os.PersistableBundleProto* com.android.nfc.x.@0
 
 # Used by framework-nfc for reading trunk stable flags
-rule android.nfc.FakeFeatureFlagsImpl* com.android.nfc.x.@0
-rule android.nfc.FeatureFlags* com.android.nfc.x.@0
-rule android.nfc.Flags* com.android.nfc.x.@0
+rule android.nfc.*Flags* com.android.nfc.x.@0
+rule android.nfc.Flags com.android.nfc.x.@0
 rule android.permission.flags.** com.android.nfc.x.@0
 
 # Used by framework-nfc for misc utilities
diff --git a/packages/CredentialManager/res/values-bs/strings.xml b/packages/CredentialManager/res/values-bs/strings.xml
index c2d452db..8d44d9c 100644
--- a/packages/CredentialManager/res/values-bs/strings.xml
+++ b/packages/CredentialManager/res/values-bs/strings.xml
@@ -48,7 +48,7 @@
     <string name="passwords" msgid="5419394230391253816">"lozinke"</string>
     <string name="sign_ins" msgid="4710739369149469208">"prijave"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"informacije o prijavi"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Sačuvaj <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> na"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Sačuvaj vrstu akreditiva \"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g>\" na"</string>
     <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Kreirati pristupni ključ na drugom uređaju?"</string>
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Sačuvati lozinku na drugom uređaju?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Sačuvati akreditive za prijavu na drugom uređaju?"</string>
diff --git a/packages/CredentialManager/res/values-ca/strings.xml b/packages/CredentialManager/res/values-ca/strings.xml
index 32405a4..95b6c29 100644
--- a/packages/CredentialManager/res/values-ca/strings.xml
+++ b/packages/CredentialManager/res/values-ca/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_name" msgid="4539824758261855508">"Gestor de credencials"</string>
     <string name="string_cancel" msgid="6369133483981306063">"Cancel·la"</string>
     <string name="string_continue" msgid="1346732695941131882">"Continua"</string>
-    <string name="string_more_options" msgid="2763852250269945472">"Desa diferent"</string>
+    <string name="string_more_options" msgid="2763852250269945472">"Desa d\'altra forma"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Més informació"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Mostra la contrasenya"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Amaga la contrasenya"</string>
@@ -74,7 +74,7 @@
     <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Utilitza el bloqueig de pantalla per iniciar la sessió a <xliff:g id="APP_NAME">%1$s</xliff:g> amb <xliff:g id="USERNAME">%2$s</xliff:g>"</string>
     <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Desbloqueja les opcions d\'inici de sessió per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Tria una clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Tria una clau d\'accés desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Tria una contrasenya desada per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Tria un inici de sessió desat per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Selecciona un compte per a <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Vols triar una opció per a <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string>
diff --git a/packages/CredentialManager/res/values-de/strings.xml b/packages/CredentialManager/res/values-de/strings.xml
index ccff535..115f544 100644
--- a/packages/CredentialManager/res/values-de/strings.xml
+++ b/packages/CredentialManager/res/values-de/strings.xml
@@ -48,7 +48,7 @@
     <string name="passwords" msgid="5419394230391253816">"Passwörter"</string>
     <string name="sign_ins" msgid="4710739369149469208">"Anmeldungen"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"Anmeldedaten"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> speichern unter"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"<xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> speichern in"</string>
     <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Passkey auf einem anderen Gerät erstellen?"</string>
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Passwort auf einem anderen Gerät speichern?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Anmeldedaten auf einem anderen Gerät speichern?"</string>
@@ -74,7 +74,7 @@
     <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"Du kannst die Displaysperre verwenden, um dich in <xliff:g id="APP_NAME">%1$s</xliff:g> als <xliff:g id="USERNAME">%2$s</xliff:g> anzumelden"</string>
     <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"Anmeldeoptionen für <xliff:g id="APP_NAME">%1$s</xliff:g> freischalten"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"Einen gespeicherten Passkey für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
-    <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Ein gespeichertes Passwort für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
+    <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"Gespeichertes Passwort für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"Gespeicherte Anmeldedaten für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"Konto für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"Option für <xliff:g id="APP_NAME">%1$s</xliff:g> auswählen?"</string>
diff --git a/packages/CredentialManager/res/values-fr/strings.xml b/packages/CredentialManager/res/values-fr/strings.xml
index c406857..b239fc3 100644
--- a/packages/CredentialManager/res/values-fr/strings.xml
+++ b/packages/CredentialManager/res/values-fr/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_name" msgid="4539824758261855508">"Gestionnaire d\'identifiants"</string>
     <string name="string_cancel" msgid="6369133483981306063">"Annuler"</string>
     <string name="string_continue" msgid="1346732695941131882">"Continuer"</string>
-    <string name="string_more_options" msgid="2763852250269945472">"Sauver autrement"</string>
+    <string name="string_more_options" msgid="2763852250269945472">"Autre façon"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"En savoir plus"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Afficher le mot de passe"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Masquer le mot de passe"</string>
diff --git a/packages/CredentialManager/res/values-ko/strings.xml b/packages/CredentialManager/res/values-ko/strings.xml
index 468f4e7..7067a40 100644
--- a/packages/CredentialManager/res/values-ko/strings.xml
+++ b/packages/CredentialManager/res/values-ko/strings.xml
@@ -89,7 +89,7 @@
     <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>
     <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_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>
     <string name="request_cancelled_by" msgid="3735222326886267820">"<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 2f6086a..e0def18 100644
--- a/packages/CredentialManager/res/values-my/strings.xml
+++ b/packages/CredentialManager/res/values-my/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_name" msgid="4539824758261855508">"အထောက်အထားမန်နေဂျာ"</string>
     <string name="string_cancel" msgid="6369133483981306063">"မလုပ်တော့"</string>
     <string name="string_continue" msgid="1346732695941131882">"ရှေ့ဆက်ရန်"</string>
-    <string name="string_more_options" msgid="2763852250269945472">"အခြားနည်း သိမ်းရန်"</string>
+    <string name="string_more_options" msgid="2763852250269945472">"အခြားနည်းသုံးရန်"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"ပိုမိုလေ့လာရန်"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"စကားဝှက်ကို ပြရန်"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"စကားဝှက်ကို ဖျောက်ရန်"</string>
diff --git a/packages/CredentialManager/res/values-or/strings.xml b/packages/CredentialManager/res/values-or/strings.xml
index 336b29f..e3a9191 100644
--- a/packages/CredentialManager/res/values-or/strings.xml
+++ b/packages/CredentialManager/res/values-or/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_name" msgid="4539824758261855508">"କ୍ରେଡେନସିଆଲ ମେନେଜର"</string>
     <string name="string_cancel" msgid="6369133483981306063">"ବାତିଲ କରନ୍ତୁ"</string>
     <string name="string_continue" msgid="1346732695941131882">"ଜାରି ରଖନ୍ତୁ"</string>
-    <string name="string_more_options" msgid="2763852250269945472">"ଅନ୍ୟ ଉପାୟରେ ସେଭ କର"</string>
+    <string name="string_more_options" msgid="2763852250269945472">"ଅନ୍ୟ ଭାବେ ସେଭ କରନ୍ତୁ"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"ଅଧିକ ଜାଣନ୍ତୁ"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"ପାସୱାର୍ଡ ଦେଖାନ୍ତୁ"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"ପାସୱାର୍ଡ ଲୁଚାନ୍ତୁ"</string>
diff --git a/packages/CredentialManager/res/values-pt-rPT/strings.xml b/packages/CredentialManager/res/values-pt-rPT/strings.xml
index 2204e02..a3476d9 100644
--- a/packages/CredentialManager/res/values-pt-rPT/strings.xml
+++ b/packages/CredentialManager/res/values-pt-rPT/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_name" msgid="4539824758261855508">"Credential Manager"</string>
     <string name="string_cancel" msgid="6369133483981306063">"Cancelar"</string>
     <string name="string_continue" msgid="1346732695941131882">"Continuar"</string>
-    <string name="string_more_options" msgid="2763852250269945472">"Guardar outra forma"</string>
+    <string name="string_more_options" msgid="2763852250269945472">"Guardar de outra forma"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Saber mais"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Mostrar palavra-passe"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Ocultar palavra-passe"</string>
diff --git a/packages/CredentialManager/res/values-ru/strings.xml b/packages/CredentialManager/res/values-ru/strings.xml
index ec2a2d6..936ff79 100644
--- a/packages/CredentialManager/res/values-ru/strings.xml
+++ b/packages/CredentialManager/res/values-ru/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_name" msgid="4539824758261855508">"Менеджер учетных данных"</string>
     <string name="string_cancel" msgid="6369133483981306063">"Отмена"</string>
     <string name="string_continue" msgid="1346732695941131882">"Продолжить"</string>
-    <string name="string_more_options" msgid="2763852250269945472">"Сохранить"</string>
+    <string name="string_more_options" msgid="2763852250269945472">"Другой способ"</string>
     <string name="string_learn_more" msgid="4541600451688392447">"Подробнее"</string>
     <string name="content_description_show_password" msgid="3283502010388521607">"Показать пароль"</string>
     <string name="content_description_hide_password" msgid="6841375971631767996">"Скрыть пароль"</string>
diff --git a/packages/CredentialManager/res/values-sq/strings.xml b/packages/CredentialManager/res/values-sq/strings.xml
index 8dc0fc2..d943979 100644
--- a/packages/CredentialManager/res/values-sq/strings.xml
+++ b/packages/CredentialManager/res/values-sq/strings.xml
@@ -48,7 +48,7 @@
     <string name="passwords" msgid="5419394230391253816">"fjalëkalime"</string>
     <string name="sign_ins" msgid="4710739369149469208">"identifikimet"</string>
     <string name="sign_in_info" msgid="2627704710674232328">"informacionet e identifikimit"</string>
-    <string name="save_credential_to_title" msgid="3172811692275634301">"Ruaj <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> te"</string>
+    <string name="save_credential_to_title" msgid="3172811692275634301">"Të ruhet <xliff:g id="CREDENTIALTYPES">%1$s</xliff:g> te"</string>
     <string name="create_passkey_in_other_device_title" msgid="2360053098931886245">"Të krijohet çelësi i kalimit në një pajisje tjetër?"</string>
     <string name="save_password_on_other_device_title" msgid="5829084591948321207">"Të ruhet fjalëkalimi në një pajisje tjetër?"</string>
     <string name="save_sign_in_on_other_device_title" msgid="2827990118560134692">"Të ruhet identifikimi në një pajisje tjetër?"</string>
diff --git a/packages/CredentialManager/res/values-tr/strings.xml b/packages/CredentialManager/res/values-tr/strings.xml
index 3c9c3b7..b423b2c 100644
--- a/packages/CredentialManager/res/values-tr/strings.xml
+++ b/packages/CredentialManager/res/values-tr/strings.xml
@@ -74,7 +74,7 @@
     <string name="get_dialog_description_single_tap" msgid="2797059565126030879">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulamasında <xliff:g id="USERNAME">%2$s</xliff:g> hesabıyla oturum açmak için ekran kilidinizi kullanın"</string>
     <string name="get_dialog_title_unlock_options_for" msgid="7096423827682163270">"<xliff:g id="APP_NAME">%1$s</xliff:g> için oturum açma seçeneklerinin kilidini açın"</string>
     <string name="get_dialog_title_choose_passkey_for" msgid="9175997688078538490">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı bir geçiş anahtarı kullanın"</string>
-    <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı bir şifre kullanın"</string>
+    <string name="get_dialog_title_choose_password_for" msgid="1724435823820819221">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı bir şifre seçin"</string>
     <string name="get_dialog_title_choose_saved_sign_in_for" msgid="2420298653461652728">"<xliff:g id="APP_NAME">%1$s</xliff:g> için kayıtlı oturum açma bilgilerini kullanın"</string>
     <string name="get_dialog_title_choose_sign_in_for" msgid="645728947702442421">"<xliff:g id="APP_NAME">%1$s</xliff:g> uygulaması için bir hesap seçin"</string>
     <string name="get_dialog_title_choose_option_for" msgid="4976380044745029107">"<xliff:g id="APP_NAME">%1$s</xliff:g> için bir seçim yapmak ister misiniz?"</string>
diff --git a/packages/CredentialManager/res/values-uk/strings.xml b/packages/CredentialManager/res/values-uk/strings.xml
index a3f79ca..cd5b7bb 100644
--- a/packages/CredentialManager/res/values-uk/strings.xml
+++ b/packages/CredentialManager/res/values-uk/strings.xml
@@ -82,7 +82,7 @@
     <string name="get_dialog_use_saved_passkey_for" msgid="4618100798664888512">"Увійти іншим способом"</string>
     <string name="snackbar_action" msgid="37373514216505085">"Переглянути варіанти"</string>
     <string name="get_dialog_button_label_continue" msgid="6446201694794283870">"Продовжити"</string>
-    <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Опції входу"</string>
+    <string name="get_dialog_title_sign_in_options" msgid="2092876443114893618">"Способи входу"</string>
     <string name="button_label_view_more" msgid="3429098227286495651">"Переглянути більше"</string>
     <string name="get_dialog_heading_for_username" msgid="3456868514554204776">"Для користувача <xliff:g id="USERNAME">%1$s</xliff:g>"</string>
     <string name="get_dialog_heading_locked_password_managers" msgid="8911514851762862180">"Заблоковані менеджери паролів"</string>
diff --git a/packages/CredentialManager/res/values-zh-rTW/strings.xml b/packages/CredentialManager/res/values-zh-rTW/strings.xml
index d5f3093..6b22e36 100644
--- a/packages/CredentialManager/res/values-zh-rTW/strings.xml
+++ b/packages/CredentialManager/res/values-zh-rTW/strings.xml
@@ -40,7 +40,7 @@
     <string name="choose_provider_title" msgid="8870795677024868108">"選擇要將<xliff:g id="CREATETYPES">%1$s</xliff:g>存在哪裡"</string>
     <string name="choose_provider_body" msgid="4967074531845147434">"選取密碼管理工具並儲存資訊,下次就能更快登入"</string>
     <string name="choose_create_option_passkey_title" msgid="8762295821604276511">"要建立用於登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」的密碼金鑰嗎?"</string>
-    <string name="choose_create_option_password_title" msgid="4481366993598649224">"要儲存用於登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」的密碼嗎?"</string>
+    <string name="choose_create_option_password_title" msgid="4481366993598649224">"要儲存登入「<xliff:g id="APP_NAME">%1$s</xliff:g>」的密碼嗎?"</string>
     <string name="choose_create_option_sign_in_title" msgid="7092914088455358079">"要儲存「<xliff:g id="APP_NAME">%1$s</xliff:g>」的登入資訊嗎?"</string>
     <string name="passkey" msgid="632353688396759522">"密碼金鑰"</string>
     <string name="password" msgid="6738570945182936667">"密碼"</string>
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index a2f55cd..8cde454 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -125,6 +125,7 @@
             return Triple(true, false, null)
         }
         val shouldShowCancellationUi = cancelUiRequest.shouldShowCancellationExplanation()
+        viewModel?.onDeveloperCancellationReceivedForBiometricPrompt()
         Log.d(
             Constants.LOG_TAG, "Received UI cancellation intent. Should show cancellation" +
             " ui = $shouldShowCancellationUi")
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
index 7bc3241..d4a8110 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorViewModel.kt
@@ -19,6 +19,7 @@
 import android.app.Activity
 import android.hardware.biometrics.BiometricPrompt
 import android.hardware.biometrics.BiometricPrompt.AuthenticationResult
+import android.os.CancellationSignal
 import android.os.IBinder
 import android.text.TextUtils
 import android.util.Log
@@ -232,8 +233,13 @@
         authResult: BiometricPrompt.AuthenticationResult? = null,
         authError: BiometricError? = null,
     ) {
-        Log.d(Constants.LOG_TAG, "credential selected: {provider=${entry.providerId}" +
-            ", key=${entry.entryKey}, subkey=${entry.entrySubkey}}")
+        if (authError == null) {
+            Log.d(Constants.LOG_TAG, "credential selected: {provider=${entry.providerId}" +
+                        ", key=${entry.entryKey}, subkey=${entry.entrySubkey}}")
+        } else {
+                Log.d(Constants.LOG_TAG, "Biometric flow error: ${authError.errorCode} " +
+                        "propagating to provider, message: ${authError.errorMessage}.")
+        }
         uiState = if (entry.pendingIntent != null) {
             uiState.copy(
                 selectedEntry = entry,
@@ -385,9 +391,15 @@
         val providerId = selectedEntry.providerId
         val entryKey = selectedEntry.entryKey
         val entrySubkey = selectedEntry.entrySubkey
-        Log.d(
-            Constants.LOG_TAG, "Option selected for entry: " +
-            " {provider=$providerId, key=$entryKey, subkey=$entrySubkey")
+        if (authError == null) {
+            Log.d(
+                Constants.LOG_TAG, "Option selected for entry: " +
+                        " {provider=$providerId, key=$entryKey, subkey=$entrySubkey"
+            )
+        } else {
+            Log.d(Constants.LOG_TAG, "Biometric flow error: ${authError.errorCode} " +
+                    "propagating to provider, message: ${authError.errorMessage}.")
+        }
         if (selectedEntry.pendingIntent != null) {
             uiState = uiState.copy(
                 selectedEntry = selectedEntry,
@@ -424,6 +436,33 @@
     /**************************************************************************/
 
     /**
+     * Cancels the biometric prompt's cancellation signal. Should only be called when the credential
+     * manager ui receives a developer cancellation signal. If the prompt is already done, we do
+     * not allow a cancellation, given the UI cancellation will be caught by the backend. We also
+     * set the biometricStatus to CANCELED, so that only in this case, we do *not* propagate the
+     * ERROR_CANCELED when a developer cancellation signal is the root cause.
+     */
+    fun onDeveloperCancellationReceivedForBiometricPrompt() {
+        val biometricCancellationSignal = uiState.biometricState.biometricCancellationSignal
+        if (!biometricCancellationSignal.isCanceled && uiState.biometricState.biometricStatus
+            != BiometricPromptState.COMPLETE) {
+            uiState = uiState.copy(
+                biometricState = uiState.biometricState.copy(
+                    biometricStatus = BiometricPromptState.CANCELED
+                )
+            )
+            biometricCancellationSignal.cancel()
+        }
+    }
+
+    /**
+     * Retrieve the biometric prompt's cancellation signal (e.g. to pass into the 'authenticate'
+     * API).
+     */
+    fun getBiometricCancellationSignal(): CancellationSignal =
+        uiState.biometricState.biometricCancellationSignal
+
+    /**
      * This allows falling back from the biometric prompt screen to the normal get flow by applying
      * a reset to all necessary states involved in the fallback.
      */
@@ -450,9 +489,9 @@
     }
 
     /**
-     * This returns the present biometric state.
+     * This returns the present biometric prompt state's status.
      */
-    fun getBiometricPromptState(): BiometricPromptState =
+    fun getBiometricPromptStateStatus(): BiometricPromptState =
         uiState.biometricState.biometricStatus
 
     /**************************************************************************/
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt
index 0d19a45..b43b5f3 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricHandler.kt
@@ -65,7 +65,6 @@
  * ).
  *
  * The above are examples; the credential type can change depending on scenario.
- * // TODO(b/333445112) : Finalize once all the strings and create flow is iterated to completion
  */
 data class BiometricDisplayInfo(
     val providerIcon: Bitmap,
@@ -84,7 +83,8 @@
 data class BiometricState(
     val biometricResult: BiometricResult? = null,
     val biometricError: BiometricError? = null,
-    val biometricStatus: BiometricPromptState = BiometricPromptState.INACTIVE
+    val biometricStatus: BiometricPromptState = BiometricPromptState.INACTIVE,
+    val biometricCancellationSignal: CancellationSignal = CancellationSignal(),
 )
 
 /**
@@ -118,6 +118,7 @@
     getBiometricPromptState: () -> BiometricPromptState,
     onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
     onBiometricFailureFallback: (BiometricFlowType) -> Unit,
+    getBiometricCancellationSignal: () -> CancellationSignal,
     getRequestDisplayInfo: RequestDisplayInfo? = null,
     getProviderInfoList: List<ProviderInfo>? = null,
     getProviderDisplayInfo: ProviderDisplayInfo? = null,
@@ -141,11 +142,13 @@
 
     val callback: BiometricPrompt.AuthenticationCallback =
         setupBiometricAuthenticationCallback(sendDataToProvider, biometricEntry,
-            onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange)
+            onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange,
+            getBiometricPromptState)
 
-    Log.d(TAG, "The BiometricPrompt API call begins.")
+    Log.d(TAG, "The BiometricPrompt API call begins for Get.")
     runBiometricFlow(context, biometricDisplayInfo, callback, openMoreOptionsPage,
-        onBiometricFailureFallback, BiometricFlowType.GET, onCancelFlowAndFinish)
+        onBiometricFailureFallback, BiometricFlowType.GET, onCancelFlowAndFinish,
+        getBiometricCancellationSignal)
 }
 
 /**
@@ -163,6 +166,7 @@
     getBiometricPromptState: () -> BiometricPromptState,
     onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
     onBiometricFailureFallback: (BiometricFlowType) -> Unit,
+    getBiometricCancellationSignal: () -> CancellationSignal,
     createRequestDisplayInfo: com.android.credentialmanager.createflow
     .RequestDisplayInfo? = null,
     createProviderInfo: EnabledProviderInfo? = null,
@@ -185,11 +189,13 @@
 
     val callback: BiometricPrompt.AuthenticationCallback =
         setupBiometricAuthenticationCallback(sendDataToProvider, biometricEntry,
-            onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange)
+            onCancelFlowAndFinish, onIllegalStateAndFinish, onBiometricPromptStateChange,
+            getBiometricPromptState)
 
-    Log.d(TAG, "The BiometricPrompt API call begins.")
+    Log.d(TAG, "The BiometricPrompt API call begins for Create.")
     runBiometricFlow(context, biometricDisplayInfo, callback, openMoreOptionsPage,
-        onBiometricFailureFallback, BiometricFlowType.CREATE, onCancelFlowAndFinish)
+        onBiometricFailureFallback, BiometricFlowType.CREATE, onCancelFlowAndFinish,
+        getBiometricCancellationSignal)
 }
 
 /**
@@ -206,7 +212,8 @@
     openMoreOptionsPage: () -> Unit,
     onBiometricFailureFallback: (BiometricFlowType) -> Unit,
     biometricFlowType: BiometricFlowType,
-    onCancelFlowAndFinish: () -> Unit
+    onCancelFlowAndFinish: () -> Unit,
+    getBiometricCancellationSignal: () -> CancellationSignal,
 ) {
     try {
         if (!canCallBiometricPrompt(biometricDisplayInfo, context)) {
@@ -217,12 +224,7 @@
         val biometricPrompt = setupBiometricPrompt(context, biometricDisplayInfo,
             openMoreOptionsPage, biometricDisplayInfo.biometricRequestInfo, onCancelFlowAndFinish)
 
-        val cancellationSignal = CancellationSignal()
-        cancellationSignal.setOnCancelListener {
-            Log.d(TAG, "Your cancellation signal was called.")
-            // TODO(b/333445112) : Migrate towards passing along the developer cancellation signal
-            // or validate the necessity for this
-        }
+        val cancellationSignal = getBiometricCancellationSignal()
 
         val executor = getMainExecutor(context)
 
@@ -251,8 +253,6 @@
  * Note that if device credential is the only available modality but not requested, or if none
  * of the requested modalities are available, we fallback to the normal flow to ensure a selector
  * shows up.
- * // TODO(b/334197980) : While we already fallback in cases the selector doesn't show, confirm
- * // final plan.
  */
 private fun canCallBiometricPrompt(
     biometricDisplayInfo: BiometricDisplayInfo,
@@ -270,12 +270,12 @@
         return false
     }
 
-    if (ifOnlySupportsAtMostDeviceCredentials(biometricManager)) return false
+    if (onlySupportsAtMostDeviceCredentials(biometricManager)) return false
 
     return true
 }
 
-private fun ifOnlySupportsAtMostDeviceCredentials(biometricManager: BiometricManager): Boolean {
+private fun onlySupportsAtMostDeviceCredentials(biometricManager: BiometricManager): Boolean {
     if (biometricManager.canAuthenticate(Authenticators.BIOMETRIC_WEAK) !=
         BiometricManager.BIOMETRIC_SUCCESS &&
         biometricManager.canAuthenticate(Authenticators.BIOMETRIC_STRONG) !=
@@ -343,11 +343,11 @@
     selectedEntry: EntryInfo,
     onCancelFlowAndFinish: () -> Unit,
     onIllegalStateAndFinish: (String) -> Unit,
-    onBiometricPromptStateChange: (BiometricPromptState) -> Unit
+    onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
+    getBiometricPromptState: () -> BiometricPromptState,
 ): BiometricPrompt.AuthenticationCallback {
     val callback: BiometricPrompt.AuthenticationCallback =
         object : BiometricPrompt.AuthenticationCallback() {
-            // TODO(b/333445772) : Validate remaining callbacks
             override fun onAuthenticationSucceeded(
                 authResult: BiometricPrompt.AuthenticationResult?
             ) {
@@ -374,6 +374,12 @@
             override fun onAuthenticationError(errorCode: Int, errString: CharSequence?) {
                 super.onAuthenticationError(errorCode, errString)
                 Log.d(TAG, "Authentication error-ed out: $errorCode and $errString")
+                if (getBiometricPromptState() == BiometricPromptState.CANCELED && errorCode
+                    == BiometricPrompt.BIOMETRIC_ERROR_CANCELED) {
+                    Log.d(TAG, "Developer cancellation signal received. Nothing more to do.")
+                    // This unique edge case means a developer cancellation signal was sent.
+                    return
+                }
                 onBiometricPromptStateChange(BiometricPromptState.COMPLETE)
                 if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED) {
                     // Note that because the biometric prompt is imbued directly
@@ -471,8 +477,7 @@
     val singleEntryType = selectedEntry.credentialType
     val username = selectedEntry.userName
 
-    // TODO(b/330396140) : Finalize localization and parsing for specific sign in option flows
-    //  (fingerprint, face, etc...))
+    // TODO(b/336362538) : In W, utilize updated localization strings
     displayTitleText = context.getString(
         generateDisplayTitleTextResCode(singleEntryType),
         getRequestDisplayInfo.appName
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt
index e1aa041..eb77937 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/common/BiometricPromptState.kt
@@ -22,5 +22,10 @@
     /** The biometric prompt is active but data hasn't been returned yet. */
     PENDING,
     /** The biometric prompt has closed and returned data we then send to the provider activity. */
-    COMPLETE
+    COMPLETE,
+    /**
+     * The biometric prompt has been canceled by a developer signal. If this is true, certain
+     * conditions can be triggered, such as no longer propagating ERROR_CANCELED.
+     */
+    CANCELED,
 }
\ 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 282a1b5..7d61f73 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -18,6 +18,7 @@
 
 import android.credentials.flags.Flags.selectorUiImprovementsEnabled
 import android.hardware.biometrics.BiometricPrompt
+import android.os.CancellationSignal
 import android.text.TextUtils
 import androidx.activity.compose.ManagedActivityResultLauncher
 import androidx.activity.result.ActivityResult
@@ -118,9 +119,11 @@
                                 fallbackToOriginalFlow =
                                 viewModel::fallbackFromBiometricToNormalFlow,
                                 getBiometricPromptState =
-                                viewModel::getBiometricPromptState,
+                                viewModel::getBiometricPromptStateStatus,
                                 onBiometricPromptStateChange =
-                                viewModel::onBiometricPromptStateChange
+                                viewModel::onBiometricPromptStateChange,
+                                getBiometricCancellationSignal =
+                                viewModel::getBiometricCancellationSignal
                             )
                         CreateScreenState.MORE_OPTIONS_SELECTION_ONLY -> MoreOptionsSelectionCard(
                                 requestDisplayInfo = createCredentialUiState.requestDisplayInfo,
@@ -638,6 +641,7 @@
     fallbackToOriginalFlow: (BiometricFlowType) -> Unit,
     getBiometricPromptState: () -> BiometricPromptState,
     onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
+    getBiometricCancellationSignal: () -> CancellationSignal,
 ) {
     if (biometricEntry == null) {
         fallbackToOriginalFlow(BiometricFlowType.CREATE)
@@ -655,5 +659,6 @@
         createProviderInfo = enabledProviderInfo,
         onBiometricFailureFallback = fallbackToOriginalFlow,
         onIllegalStateAndFinish = onIllegalScreenStateAndFinish,
+        getBiometricCancellationSignal = getBiometricCancellationSignal,
     )
 }
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
index c98bb5e..ba61b90 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/getflow/GetCredentialComponents.kt
@@ -20,6 +20,7 @@
 import android.credentials.flags.Flags.selectorUiImprovementsEnabled
 import android.graphics.drawable.Drawable
 import android.hardware.biometrics.BiometricPrompt
+import android.os.CancellationSignal
 import androidx.activity.compose.ManagedActivityResultLauncher
 import androidx.activity.result.ActivityResult
 import androidx.activity.result.IntentSenderRequest
@@ -161,9 +162,11 @@
                                 fallbackToOriginalFlow =
                                 viewModel::fallbackFromBiometricToNormalFlow,
                                 getBiometricPromptState =
-                                viewModel::getBiometricPromptState,
+                                viewModel::getBiometricPromptStateStatus,
                                 onBiometricPromptStateChange =
-                                viewModel::onBiometricPromptStateChange
+                                viewModel::onBiometricPromptStateChange,
+                                getBiometricCancellationSignal =
+                                viewModel::getBiometricCancellationSignal
                             )
                         } else if (credmanBiometricApiEnabled() &&
                                 getCredentialUiState.currentScreenState
@@ -256,6 +259,7 @@
     fallbackToOriginalFlow: (BiometricFlowType) -> Unit,
     getBiometricPromptState: () -> BiometricPromptState,
     onBiometricPromptStateChange: (BiometricPromptState) -> Unit,
+    getBiometricCancellationSignal: () -> CancellationSignal,
 ) {
     if (biometricEntry == null) {
         fallbackToOriginalFlow(BiometricFlowType.GET)
@@ -273,7 +277,8 @@
         getRequestDisplayInfo = requestDisplayInfo,
         getProviderInfoList = providerInfoList,
         getProviderDisplayInfo = providerDisplayInfo,
-        onBiometricFailureFallback = fallbackToOriginalFlow
+        onBiometricFailureFallback = fallbackToOriginalFlow,
+        getBiometricCancellationSignal = getBiometricCancellationSignal
     )
 }
 
diff --git a/packages/InputDevices/res/raw/keyboard_layout_thai_pattachote.kcm b/packages/InputDevices/res/raw/keyboard_layout_thai_pattachote.kcm
new file mode 100644
index 0000000..a136aca
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_thai_pattachote.kcm
@@ -0,0 +1,317 @@
+# Copyright 2024 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Thai Pattachote keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '_'
+    base:                               '_'
+    shift, capslock:                    '\u0e3f'
+}
+
+key 1 {
+    label:                              '='
+    base:                               '='
+    shift, capslock:                    '+'
+}
+
+key 2 {
+    label:                              '\u0e52'
+    base:                               '\u0e52'
+    shift, capslock:                    '\u0022'
+}
+
+key 3 {
+    label:                              '\u0e53'
+    base:                               '\u0e53'
+    shift, capslock:                    '/'
+}
+
+key 4 {
+    label:                              '\u0e54'
+    base:                               '\u0e54'
+    shift, capslock:                    ','
+}
+
+key 5 {
+    label:                              '\u0e55'
+    base:                               '\u0e55'
+    shift, capslock:                    '?'
+}
+
+key 6 {
+    label:                              '\u0e39'
+    base:                               '\u0e39'
+    shift, capslock:                    '\u0e38'
+}
+
+key 7 {
+    label:                              '\u0e57'
+    base:                               '\u0e57'
+    shift, capslock:                    '_'
+}
+
+key 8 {
+    label:                              '\u0e58'
+    base:                               '\u0e58'
+    shift, capslock:                    '.'
+}
+
+key 9 {
+    label:                              '\u0e59'
+    base:                               '\u0e59'
+    shift, capslock:                    '('
+}
+
+key 0 {
+    label:                              '\u0e50'
+    base:                               '\u0e50'
+    shift, capslock:                    ')'
+}
+
+key MINUS {
+    label:                              '\u0e51'
+    base:                               '\u0e51'
+    shift, capslock:                    '-'
+}
+
+key EQUALS {
+    label:                              '\u0e56'
+    base:                               '\u0e56'
+    shift, capslock:                    '%'
+}
+
+### ROW 2
+
+key Q {
+    label:                              '\u0e47'
+    base:                               '\u0e47'
+    shift, capslock:                    '\u0e4a'
+}
+
+key W {
+    label:                              '\u0e15'
+    base:                               '\u0e15'
+    shift, capslock:                    '\u0e24'
+}
+
+key E {
+    label:                              '\u0e22'
+    base:                               '\u0e22'
+    shift, capslock:                    '\u0e46'
+}
+
+key R {
+    label:                              '\u0e2d'
+    base:                               '\u0e2d'
+    shift, capslock:                    '\u0e0d'
+}
+
+key T {
+    label:                              '\u0e23'
+    base:                               '\u0e23'
+    shift, capslock:                    '\u0e29'
+}
+
+key Y {
+    label:                              '\u0e48'
+    base:                               '\u0e48'
+    shift, capslock:                    '\u0e36'
+}
+
+key U {
+    label:                              '\u0e14'
+    base:                               '\u0e14'
+    shift, capslock:                    '\u0e1d'
+}
+
+key I {
+    label:                              '\u0e21'
+    base:                               '\u0e21'
+    shift, capslock:                    '\u0e0b'
+}
+
+key O {
+    label:                              '\u0e27'
+    base:                               '\u0e27'
+    shift, capslock:                    '\u0e16'
+}
+
+key P {
+    label:                              '\u0e41'
+    base:                               '\u0e41'
+    shift, capslock:                    '\u0e12'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u0e43'
+    base:                               '\u0e43'
+    shift, capslock:                    '\u0e2f'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u0e0c'
+    base:                               '\u0e0c'
+    shift, capslock:                    '\u0e26'
+}
+
+### ROW 3
+
+key A {
+    label:                              '\u0e49'
+    base:                               '\u0e49'
+    shift, capslock:                    '\u0e4b'
+}
+
+key S {
+    label:                              '\u0e17'
+    base:                               '\u0e17'
+    shift, capslock:                    '\u0e18'
+}
+
+key D {
+    label:                              '\u0e07'
+    base:                               '\u0e07'
+    shift, capslock:                    '\u0e33'
+}
+
+key F {
+    label:                              '\u0e01'
+    base:                               '\u0e01'
+    shift, capslock:                    '\u0e13'
+}
+
+key G {
+    label:                              '\u0e31'
+    base:                               '\u0e31'
+    shift, capslock:                    '\u0e4c'
+}
+
+key H {
+    label:                              '\u0e35'
+    base:                               '\u0e35'
+    shift, capslock:                    '\u0e37'
+}
+
+key J {
+    label:                              '\u0e32'
+    base:                               '\u0e32'
+    shift, capslock:                    '\u0e1c'
+}
+
+key K {
+    label:                              '\u0e19'
+    base:                               '\u0e19'
+    shift, capslock:                    '\u0e0a'
+}
+
+key L {
+    label:                              '\u0e40'
+    base:                               '\u0e40'
+    shift, capslock:                    '\u0e42'
+}
+
+key SEMICOLON {
+    label:                              '\u0e44'
+    base:                               '\u0e44'
+    shift, capslock:                    '\u0e06'
+}
+
+key APOSTROPHE {
+    label:                              '\u0e02'
+    base:                               '\u0e02'
+    shift, capslock:                    '\u0e11'
+}
+
+key BACKSLASH {
+    label:                              '\u0e45'
+    base:                               '\u0e45'
+    shift, capslock:                    '\u0e4d'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '\u0e45'
+    base:                               '\u0e45'
+    shift, capslock:                    '\u0e4d'
+}
+
+key Z {
+    label:                              '\u0e1a'
+    base:                               '\u0e1a'
+    shift, capslock:                    '\u0e0e'
+}
+
+key X {
+    label:                              '\u0e1b'
+    base:                               '\u0e1b'
+    shift, capslock:                    '\u0e0f'
+}
+
+key C {
+    label:                              '\u0e25'
+    base:                               '\u0e25'
+    shift, capslock:                    '\u0e10'
+}
+
+key V {
+    label:                              '\u0e2b'
+    base:                               '\u0e2b'
+    shift, capslock:                    '\u0e20'
+}
+
+key B {
+    label:                              '\u0e34'
+    base:                               '\u0e34'
+    shift, capslock:                    '\u0e31'
+}
+
+key N {
+    label:                              '\u0e04'
+    base:                               '\u0e04'
+    shift, capslock:                    '\u0e28'
+}
+
+key M {
+    label:                              '\u0e2a'
+    base:                               '\u0e2a'
+    shift, capslock:                    '\u0e2e'
+}
+
+key COMMA {
+    label:                              '\u0e30'
+    base:                               '\u0e30'
+    shift, capslock:                    '\u0e1f'
+}
+
+key PERIOD {
+    label:                              '\u0e08'
+    base:                               '\u0e08'
+    shift, capslock:                    '\u0e09'
+}
+
+key SLASH {
+    label:                              '\u0e1e'
+    base:                               '\u0e1e'
+    shift, capslock:                    '\u0e2c'
+}
\ No newline at end of file
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 33a1d76..e10bd7f 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -149,4 +149,7 @@
 
     <!-- Thai (Kedmanee variant) keyboard layout label. [CHAR LIMIT=35] -->
     <string name="keyboard_layout_thai_kedmanee">Thai (Kedmanee)</string>
+
+    <!-- Thai (Pattachote variant) keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_thai_pattachote">Thai (Pattachote)</string>
 </resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 4b7ea90..c18d73c 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -325,4 +325,11 @@
         android:keyboardLayout="@raw/keyboard_layout_thai_kedmanee"
         android:keyboardLocale="th-Thai"
         android:keyboardLayoutType="extended" />
+
+    <keyboard-layout
+        android:name="keyboard_layout_thai_pattachote"
+        android:label="@string/keyboard_layout_thai_pattachote"
+        android:keyboardLayout="@raw/keyboard_layout_thai_pattachote"
+        android:keyboardLocale="th-Thai"
+        android:keyboardLayoutType="extended" />
 </keyboard-layouts>
diff --git a/packages/PackageInstaller/res/values-pt-rPT/strings.xml b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
index c39956d..a0a1eb9 100644
--- a/packages/PackageInstaller/res/values-pt-rPT/strings.xml
+++ b/packages/PackageInstaller/res/values-pt-rPT/strings.xml
@@ -99,7 +99,7 @@
     <string name="untrusted_external_source_warning" product="watch" msgid="7195163388090818636">"Para sua segurança, o relógio não está atualmente autorizado a instalar apps desconhecidas a partir desta origem. Pode alterar esta opção nas Definições."</string>
     <string name="untrusted_external_source_warning" product="default" msgid="8444191224459138919">"Para sua segurança, o telemóvel não está atualmente autorizado a instalar apps desconhecidas a partir desta origem. Pode alterar esta opção nas Definições."</string>
     <string name="anonymous_source_warning" product="default" msgid="2784902545920822500">"O seu telemóvel e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta app, concorda que é responsável por quaisquer danos causados ao telemóvel ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
-    <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"O seu tablet e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta app, concorda que é responsável por quaisquer danos causados ao tablet ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
+    <string name="anonymous_source_warning" product="tablet" msgid="3939101621438855516">"O seu tablet e os dados pessoais estão mais vulneráveis a ataques por parte de apps desconhecidas. Ao instalar esta app, concorda que é responsável por quaisquer danos causados ao tablet ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
     <string name="anonymous_source_warning" product="tv" msgid="5599483539528168566">"A sua TV e os dados pessoais estão mais vulneráveis a ataques por parte de aplicações desconhecidas. Ao instalar esta app, concorda que é responsável por quaisquer danos causados à TV ou pelas perdas de dados que possam resultar da utilização da mesma."</string>
     <string name="cloned_app_label" msgid="7503612829833756160">"Clone de <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>"</string>
     <string name="archiving_app_label" msgid="1127085259724124725">"Arquivar <xliff:g id="PACKAGE_LABEL">%1$s</xliff:g>?"</string>
diff --git a/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java b/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java
index 5b2fa1d..05507e0 100644
--- a/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java
+++ b/packages/SettingsLib/FooterPreference/src/com/android/settingslib/widget/FooterPreference.java
@@ -17,10 +17,15 @@
 package com.android.settingslib.widget;
 
 import android.content.Context;
+import android.content.Intent;
 import android.text.SpannableString;
+import android.text.Spanned;
 import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
 import android.text.style.URLSpan;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.View;
 import android.widget.TextView;
 
@@ -32,18 +37,20 @@
 
 import com.android.settingslib.widget.preference.footer.R;
 
+import java.net.URISyntaxException;
+
 /**
  * A custom preference acting as "footer" of a page. It has a field for icon and text. It is added
  * to screen as the last preference.
  */
 public class FooterPreference extends Preference {
+    private static final String TAG = "FooterPreference";
 
     public static final String KEY_FOOTER = "footer_preference";
+    private static final String INTENT_URL_PREFIX = "intent:";
     static final int ORDER_FOOTER = Integer.MAX_VALUE - 1;
-    @VisibleForTesting
-    View.OnClickListener mLearnMoreListener;
-    @VisibleForTesting
-    int mIconVisibility = View.VISIBLE;
+    @VisibleForTesting View.OnClickListener mLearnMoreListener;
+    @VisibleForTesting int mIconVisibility = View.VISIBLE;
     private CharSequence mContentDescription;
     private CharSequence mLearnMoreText;
     private FooterLearnMoreSpan mLearnMoreSpan;
@@ -57,12 +64,56 @@
         this(context, null);
     }
 
+    private void linkifyTitle(TextView title) {
+        final CharSequence text = getTitle();
+        if (!(text instanceof Spanned)) {
+            return;
+        }
+        final ClickableSpan[] spans =
+                ((Spanned) text).getSpans(0, text.length(), ClickableSpan.class);
+        if (spans.length == 0) {
+            return;
+        }
+        SpannableString spannable = new SpannableString(text);
+        for (ClickableSpan clickable : spans) {
+            if (!(clickable instanceof URLSpan)) {
+                continue;
+            }
+            final URLSpan urlSpan = (URLSpan) clickable;
+            if (!urlSpan.getURL().startsWith(INTENT_URL_PREFIX)) {
+                continue;
+            }
+            final int start = spannable.getSpanStart(urlSpan);
+            final int end = spannable.getSpanEnd(urlSpan);
+            spannable.removeSpan(urlSpan);
+            try {
+                final Intent intent = Intent.parseUri(urlSpan.getURL(), Intent.URI_INTENT_SCHEME);
+                final ClickableSpan clickableSpan =
+                        new ClickableSpan() {
+                            @Override
+                            public void onClick(@NonNull View textView) {
+                                // May throw ActivityNotFoundException. Just let it propagate.
+                                getContext().startActivity(intent);
+                            }
+                        };
+                spannable.setSpan(clickableSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+            } catch (URISyntaxException e) {
+                Log.e(TAG, "Invalid URI " + urlSpan.getURL(), e);
+            }
+        }
+        title.setText(spannable);
+        title.setMovementMethod(LinkMovementMethod.getInstance());
+    }
+
     @Override
     public void onBindViewHolder(PreferenceViewHolder holder) {
         super.onBindViewHolder(holder);
         TextView title = holder.itemView.findViewById(android.R.id.title);
-        if (title != null && !TextUtils.isEmpty(mContentDescription)) {
-            title.setContentDescription(mContentDescription);
+        if (title != null) {
+            if (!TextUtils.isEmpty(mContentDescription)) {
+                title.setContentDescription(mContentDescription);
+            }
+            linkifyTitle(title);
         }
 
         TextView learnMore = holder.itemView.findViewById(R.id.settingslib_learn_more);
@@ -79,8 +130,7 @@
                     learnMoreText.removeSpan(mLearnMoreSpan);
                 }
                 mLearnMoreSpan = new FooterLearnMoreSpan(mLearnMoreListener);
-                learnMoreText.setSpan(mLearnMoreSpan, 0,
-                        learnMoreText.length(), 0);
+                learnMoreText.setSpan(mLearnMoreSpan, 0, learnMoreText.length(), 0);
                 learnMore.setText(learnMoreText);
             } else {
                 learnMore.setVisibility(View.GONE);
@@ -121,9 +171,7 @@
         }
     }
 
-    /**
-     * Return the content description of footer preference.
-     */
+    /** Return the content description of footer preference. */
     @VisibleForTesting
     CharSequence getContentDescription() {
         return mContentDescription;
@@ -141,9 +189,7 @@
         }
     }
 
-    /**
-     * Assign an action for the learn more link.
-     */
+    /** Assign an action for the learn more link. */
     public void setLearnMoreAction(View.OnClickListener listener) {
         if (mLearnMoreListener != listener) {
             mLearnMoreListener = listener;
@@ -151,9 +197,7 @@
         }
     }
 
-    /**
-     * Set visibility of footer icon.
-     */
+    /** Set visibility of footer icon. */
     public void setIconVisibility(int iconVisibility) {
         if (mIconVisibility == iconVisibility) {
             return;
@@ -174,9 +218,7 @@
         setSelectable(false);
     }
 
-    /**
-     * The builder is convenient to creat a dynamic FooterPreference.
-     */
+    /** The builder is convenient to creat a dynamic FooterPreference. */
     public static class Builder {
         private Context mContext;
         private String mKey;
@@ -241,8 +283,8 @@
         }
 
         /**
-         * To set learn more string of the learn more text. This can use for talkback
-         * environment if developer wants to have a customization content.
+         * To set learn more string of the learn more text. This can use for talkback environment if
+         * developer wants to have a customization content.
          *
          * @param learnMoreText The resource id of the learn more string.
          */
@@ -262,10 +304,7 @@
             return this;
         }
 
-
-        /**
-         * To generate the {@link FooterPreference}.
-         */
+        /** To generate the {@link FooterPreference}. */
         public FooterPreference build() {
             final FooterPreference footerPreference = new FooterPreference(mContext);
             footerPreference.setSelectable(false);
@@ -288,9 +327,7 @@
         }
     }
 
-    /**
-     * A {@link URLSpan} that opens a support page when clicked
-     */
+    /** A {@link URLSpan} that opens a support page when clicked */
     static class FooterLearnMoreSpan extends URLSpan {
 
         private final View.OnClickListener mClickListener;
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
index b7f2c1e..90cee16 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/theme/SettingsDimension.kt
@@ -22,12 +22,14 @@
 object SettingsDimension {
     val paddingTiny = 2.dp
     val paddingSmall = 4.dp
+    val paddingLarge = 16.dp
+    val paddingExtraLarge = 24.dp
 
     val itemIconSize = 24.dp
     val itemIconContainerSize = 72.dp
-    val itemPaddingStart = 24.dp
-    val itemPaddingEnd = 16.dp
-    val itemPaddingVertical = 16.dp
+    val itemPaddingStart = paddingExtraLarge
+    val itemPaddingEnd = paddingLarge
+    val itemPaddingVertical = paddingLarge
     val itemPadding = PaddingValues(
         start = itemPaddingStart,
         top = itemPaddingVertical,
@@ -70,6 +72,6 @@
     /** The sizes info of illustration widget. */
     val illustrationMaxWidth = 412.dp
     val illustrationMaxHeight = 300.dp
-    val illustrationPadding = 16.dp
+    val illustrationPadding = paddingLarge
     val illustrationCornerRadius = 28.dp
 }
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
index 163766a..e39b175 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/widget/scaffold/SuwScaffold.kt
@@ -101,7 +101,13 @@
     imageVector: ImageVector,
     title: String
 ) {
-    Column(Modifier.padding(SettingsDimension.itemPadding)) {
+    Column(
+        Modifier.padding(
+            start = SettingsDimension.itemPaddingStart,
+            top = SettingsDimension.itemPaddingVertical,
+            end = SettingsDimension.itemPaddingEnd,
+        )
+    ) {
         Icon(
             imageVector = imageVector,
             contentDescription = null,
@@ -124,7 +130,14 @@
     actionButton: BottomAppBarButton?,
     dismissButton: BottomAppBarButton?,
 ) {
-    Row(modifier = Modifier.padding(SettingsDimension.itemPaddingAround)) {
+    Row(
+        Modifier.padding(
+            start = SettingsDimension.itemPaddingEnd,
+            top = SettingsDimension.paddingExtraLarge,
+            end = SettingsDimension.itemPaddingEnd,
+            bottom = SettingsDimension.itemPaddingVertical,
+        )
+    ) {
         dismissButton?.apply {
             TextButton(onClick = onClick, enabled = enabled) {
                 ActionText(text)
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index f9800b3..9641204 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -94,41 +94,32 @@
     <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"Gekoppel (geen foon nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"Gekoppel (geen media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Gekoppel (geen foon of media nie), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <!-- no translation found for bluetooth_active_battery_level (2685517576209066008) -->
+    <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Aktief. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+    <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Aktief. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
-    <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
-    <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batterykrag"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
-    <!-- no translation found for bluetooth_battery_level_untethered (1616774716076301755) -->
-    <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left (5725764679536058365) -->
-    <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right (8377995536997790142) -->
-    <skip />
+    <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+    <string name="bluetooth_battery_level_untethered_left" msgid="5725764679536058365">"Links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
+    <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Regs: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktief"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Gestoor"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktief, net links"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktief, net regs"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktief, links en regs"</string>
-    <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
     <skip />
-    <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_lea_support (5968584103507988820) -->
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
     <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_lea_support (803110681688633362) -->
-    <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_left_lea_support (7707464334346454950) -->
-    <skip />
-    <!-- no translation found for bluetooth_battery_level_untethered_right_lea_support (8941549024377771038) -->
-    <skip />
-    <!-- no translation found for bluetooth_no_battery_level_lea_support (5721725041048434075) -->
-    <skip />
+    <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktief (net media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+    <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiewe (net media). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string>
+    <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Gekoppel (steun oudiodeling). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
+    <string name="bluetooth_battery_level_untethered_lea_support" msgid="803110681688633362">"Gekoppel (steun oudiodeling). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
+    <string name="bluetooth_battery_level_untethered_left_lea_support" msgid="7707464334346454950">"Gekoppel (steun oudiodeling). Links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+    <string name="bluetooth_battery_level_untethered_right_lea_support" msgid="8941549024377771038">"Gekoppel (steun oudiodeling). Regs: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+    <string name="bluetooth_no_battery_level_lea_support" msgid="5721725041048434075">"Gekoppel (steun oudiodeling)"</string>
     <string name="bluetooth_active_media_only_no_battery_level" msgid="71106861912593126">"Aktief (net media)"</string>
     <string name="bluetooth_saved_device_lea_support" msgid="7231323139968285768">"Steun oudiodeling"</string>
     <string name="bluetooth_hearing_aid_media_only_left_active" msgid="1632152540901488645">"Aktief (net media), net linkerkant"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 729ac28..51cf441 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ባትሪ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ንቁ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ተቀምጧል"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ገቢር፣ ግራ ብቻ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ገቢር፣ ቀኝ ብቻ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ገቢር፣ ግራ እና ቀኝ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 9f13551..b1a7332 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"مستوى طاقة البطارية <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"‏مستوى شحن البطارية: ‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"نشط"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"محفوظ"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"السمّاعة الطبية اليسرى فقط مفعَّلة"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"السمّاعة الطبية اليمنى فقط مفعَّلة"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"السمّاعتان اليسرى واليمنى مفعَّلتان"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 62c1201..13b639a 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"সক্ৰিয়"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ছেভ কৰা হৈছে"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"কেৱল বাঁওফালৰটো সক্ৰিয় হৈছে"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"কেৱল সোঁফালৰটো সক্ৰিয় হৈছে"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"বাওঁ আৰু সোঁ দুয়োফালৰ সক্ৰিয় হৈছে"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index b1bbf34..809601e 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batareya: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Yadda saxlandı"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, yalnız sol"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, yalnız sağ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, sol və sağ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 4af26f2..24830b4 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Nivo baterije je <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Sačuvano"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo s leve strane"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, s desne strane"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, s leve i desne strane"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 9998c9e..986c089 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Узровень зараду: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Уключана"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Захавана"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Уключана, толькі для левага вуха"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Уключана, толькі для правага вуха"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Уключана, для левага і правага вуха"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 03065c6..7097078 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерия: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активно"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Запазено"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно – само лявото"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно – само дясното"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно – лявото и дясното"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index b69a542..e4637fe 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"চার্জ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"চালু আছে"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"সেভ করা আছে"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"শুধুমাত্র বাঁদিকের হিয়ারিং এড অ্যাক্টিভ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"শুধুমাত্র ডানদিকের হিয়ারিং এড অ্যাক্টিভ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"বাঁ ও ডানদিকের হিয়ারিং এড, অ্যাক্টিভ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 2cc6dc5..e71c2ec 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Sačuvano"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo lijevi"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desni"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, lijevi i desni"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5a4a923..09b4297 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actiu"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Desat"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actiu, només l\'esquerre"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actiu, només el dret"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actiu, esquerre i dret"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 9a3ba63..b2d75bd 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterie"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterie <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivní"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Uloženo"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivní, pouze levé"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivní, pouze pravé"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivní, levé a pravé"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index c7f1c6e..0f92316 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Gemt"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, kun venstre"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, kun højre"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, venstre og højre"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index cc962b4..c8d7acd 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Akkustand: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akku – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Gespeichert"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, nur links"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, nur rechts"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, links und rechts"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 2ea96a7..2cc9350 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Μπαταρία <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ενεργό"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Αποθηκεύτηκε"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ενεργό, μόνο το αριστερό"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ενεργό, μόνο το δεξί"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ενεργό, αριστερό και δεξί"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index d4f14f4..af00515 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 6b49bc9..bc08544 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -96,10 +96,8 @@
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"Connected (no phone or media), battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
     <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"Active. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
     <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
-    <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
-    <skip />
+    <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"Active. L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
+    <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"Active. R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
@@ -107,9 +105,9 @@
     <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"Right: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
+    <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Active (left only)"</string>
+    <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Active (right only)"</string>
+    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Active (left and right)"</string>
     <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
     <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string>
     <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index d4f14f4..af00515 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index d4f14f4..af00515 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Battery <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Active"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saved"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Active, left only"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, right only"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, left and right"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index c255633..b123a13 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -96,10 +96,8 @@
     <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‎‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‎‎Connected (no phone or media), battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="bluetooth_active_battery_level" msgid="2685517576209066008">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎‎‎Active. ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
     <string name="bluetooth_active_battery_level_untethered" msgid="4961338936672922617">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‏‏‏‎‎‏‎Active. L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
-    <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
-    <skip />
+    <string name="bluetooth_active_battery_level_untethered_left" msgid="2895644748625343977">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‎Active. L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
+    <string name="bluetooth_active_battery_level_untethered_right" msgid="7407517998880370179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎Active. R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‎‎‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‎‏‎‏‎‏‏‏‎‎Battery ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="bluetooth_battery_level_untethered" msgid="1616774716076301755">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
@@ -107,9 +105,9 @@
     <string name="bluetooth_battery_level_untethered_right" msgid="8377995536997790142">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‎‎Right: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery‎‏‎‎‏‎"</string>
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‎Active‎‏‎‎‏‎"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎Saved‎‏‎‎‏‎"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‎‎‏‎Active, left only‎‏‎‎‏‎"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎Active, right only‎‏‎‎‏‎"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎Active, left and right‎‏‎‎‏‎"</string>
+    <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‎‎‎‏‎‏‎‏‎‎‎Active (left only)‎‏‎‎‏‎"</string>
+    <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‏‏‏‏‎‏‎‏‎Active (right only)‎‏‎‎‏‎"</string>
+    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‎‎‎‎‎‎‏‏‎‎‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎Active (left and right)‎‏‎‎‏‎"</string>
     <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‎‎‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎Active (media only). ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
     <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‎‎Active (media only). L: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>‎‏‎‎‏‏‏‎, R: ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
     <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‎‎‎‏‎‎‎‏‎‏‎‏‎‏‎‎‎Connected (supports audio sharing). ‎‏‎‎‏‏‎<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ battery.‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 6a40c42..5142f24 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activado"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo; solo oído izquierdo"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo; solo oído derecho"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activo; oídos izquierdo y derecho"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index ab75219..7dc1225 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo, solo oído izquierdo"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo, solo oído derecho"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activo, oídos izquierdo y derecho"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index c730457..a47a218 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> akut"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akutase: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiivne"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvestatud"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiivne, ainult vasak"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiivne, ainult parem"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiivne, vasak ja parem"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 0668fb2..91b9d20be 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktibo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Gordeta"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, ezkerrekoa soilik"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, eskuinekoa soilik"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktibo, ezkerreko eta eskuineko audifonoak"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 3c7f1f8..7ab13ba 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> شارژ باتری"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"باتری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"فعال"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ذخیره‌شده"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"فعال، فقط چپ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"فعال، فقط راست"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"فعال، چپ و راست"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index da80499..cafeb1b 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Akun taso <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akku (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiivinen"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Tallennettu"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiivinen, vain vasen"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiivinen, vain oikea"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiivinen, vasen ja oikea"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 6988384..0d96205 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pile : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actif"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Enregistré"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actif, gauche seulement"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Active, droite seulement"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Active, gauche et droite"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 709477b..1928f32 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batterie (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>)"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actif"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Enregistré"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actif, gauche uniquement"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actif, droit uniquement"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actifs, gauche et droit"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index e5c7f1e..d0f47a8 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batería: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Gardado"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activo (só o esquerdo)"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activo (só o dereito)"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activos (o esquerdo e o dereito)"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index d520536..b750ae5 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"બૅટરી <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"સક્રિય"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"સાચવેલું"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"સક્રિય, માત્ર ડાબું"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"સક્રિય, માત્ર જમણું"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"સક્રિય, ડાબું અને જમણું બન્ને"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index a81daf7..0f0d516 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"चालू"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"सेव किया गया"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"सिर्फ़ बाईं तरफ़ वाला चालू है"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"सिर्फ़ दाईं तरफ़ वाला चालू है"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"बाईं और दाईं तरफ़ वाला चालू है"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 362393e..db2c318 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivan"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Spremljeno"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo lijevo"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desno"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, lijevo i desno"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index f251464..207e84a 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akkumulátor: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktív"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Mentve"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktív, csak bal"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktív, csak jobb"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktív, bal és jobb"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 4b6d727..1b8b236 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ակտիվ է"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Պահված է"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ակտիվ, միայն ձախ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ակտիվ, միայն աջ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ակտիվ, ձախ և աջ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 1594d11..d9730b3 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktif"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Disimpan"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktif, hanya kiri"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktif, hanya kanan"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktif, kiri dan kanan"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index b85f453..60370f5 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Rafhlaða <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Virkt"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Vistað"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Virkt, aðeins vinstra"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Virkt, aðeins hægra"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Virkt, vinstra og hægra"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 08a2397..fbae08d 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Attivo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Dispositivo salvato"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Attiva, solo sinistra"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Attiva, solo destra"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Attivo, destra e sinistra"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 9ecf47b..5a6c751 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"טעינת הסוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"סוללה <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"פעיל"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"בוצעה שמירה"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"פועל: שמאל בלבד"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"פועל: ימין בלבד"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"פועל: ימין ושמאל"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index a51ba39..aac7223 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"バッテリー <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"バッテリー <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"有効"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"保存済み"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"有効、左のみ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"有効、右のみ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"有効、左と右"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index ba1dae0..79dbbe7 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ბატარეა"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"აქტიური"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"შენახული"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"აქტიური, მხოლოდ მარცხნივ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"აქტიური, მხოლოდ მარჯვნივ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"აქტიური, მარცხნივ და მარჯვნივ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index b8f8fa3..eee0ac6 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батарея қуаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Қосулы"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Сақталған"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Тек сол жағы қосулы"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Тек оң жағы қосулы"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Екеуі де қосулы"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index d049fd4..447126b 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"សកម្ម"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"បាន​រក្សាទុក"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"សកម្ម ខាងឆ្វេងតែប៉ុណ្ណោះ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"សកម្មខាងស្ដាំតែប៉ុណ្ណោះ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"សកម្មខាងឆ្វេង និងស្ដាំ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 70257de..f8d3b73 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಇದೆ"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ಸಕ್ರಿಯ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ಎಡಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ಬಲಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ಎಡ ಮತ್ತು ಬಲಕಿವಿಯ ಸಾಧನಗಳು ಸಕ್ರಿಯವಾಗಿವೆ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 9ced8a0..b6988ce 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"배터리 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"활성"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"저장됨"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"활성, 왼쪽만"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"활성, 오른쪽만"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"활성, 왼쪽 및 오른쪽"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 7be7f38..d084a9bf 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батареянын деңгээли: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батареянын кубаты: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Жигердүү"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Сакталган"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Иштеп жатат, сол кулак гана"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Жигердүү, оң кулакчын гана"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Жигердүү, сол жана оң кулакчын"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index c6a5bd4..19bea08 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ອອນລາຍ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ບັນທຶກແລ້ວ"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ນຳໃຊ້ຢູ່, ຊ້າຍເທົ່ານັ້ນ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ນຳໃຊ້ຢູ່, ຂວາເທົ່ານັ້ນ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ນຳໃຊ້ຢູ່, ຊ້າຍ ແລະ ຂວາ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 94b8173..4f7b350 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Akumuliatoriaus įkrova: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akumuliatorius: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktyvus"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Išsaugota"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktyvus, tik kairysis"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktyvus, tik dešinysis"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktyvus, kairysis ir dešinysis"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index ff1f3f3..55fa4d3 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktīvs"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saglabāta"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ierīce aktīva, tikai kreisā auss"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ierīce aktīva, tikai labā auss"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ierīces aktīvas, kreisā un labā auss"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index c5b4a5e..6d3d54c 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерија: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активен"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Зачувано"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно, само лево"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно, само десно"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно, лево и десно"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 0ba9122..914b967 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ബാറ്ററി ചാർജ് <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ആണ്"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"സജീവം"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"സംരക്ഷിച്ചു"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"സജീവമാണ്, ഇടത്തേത് മാത്രം"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"സജീവമാണ്, വലത്തേത് മാത്രം"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"സജീവമാണ്, ഇടത്തേതും വലത്തേതും"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index c431857..c39717c 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарей <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Идэвхтэй"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Хадгалсан"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Идэвхтэй, зөвхөн зүүн тал"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Идэвхтэй, зөвхөн баруун тал"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Идэвхтэй, зүүн болон баруун тал"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index a916a1c..5c5ec07 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"बॅटरी <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"अ‍ॅक्टिव्ह"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"सेव्ह केली आहेत"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"फक्त डावे अ‍ॅक्टिव्ह आहे"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"फक्त उजवे अ‍ॅक्टिव्ह आहे"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"डावे आणि उजवे अ‍ॅक्टिव्ह आहे"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index f86206c..b36098b 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktif"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Disimpan"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktif, kiri sahaja"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktif, kanan sahaja"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktif, kiri dan kanan"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 2dde99f..23c892f 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ဖွင့်ထားသည်"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"သိမ်းထားသည်များ"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ဖွင့်ထားသည်၊ ဘယ်သီးသန့်"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ဖွင့်ထားသည်၊ ညာသီးသန့်"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ဖွင့်ထားသည်၊ ဘယ်နှင့် ညာ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index d2021ba..d7814eb 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Lagret"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, bare venstre"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, bare høyre"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, venstre og høyre"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index d01fc16..a7e01a1 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"ब्याट्रीको स्तर: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ब्याट्री <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"सक्रिय"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"सेभ गरिएको"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"बायाँ मात्र अन छ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"सक्रिय, दायाँ मात्र"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"सक्रिय, बायाँ र दायाँ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 6394cb6..3f2e003 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batterij <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Actief"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Opgeslagen"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Actief, alleen links"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Actief, alleen rechts"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Actief, links en rechts"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index eb31f96..b233b544 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ବେଟେରୀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ସକ୍ରିୟ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ସେଭ କରାଯାଇଛି"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ସକ୍ରିୟ, କେବଳ ବାମ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ସକ୍ରିୟ, କେବଳ ଡାହାଣ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ସକ୍ରିୟ, ବାମ ଏବଂ ଡାହାଣ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
@@ -195,7 +198,7 @@
     <string name="accessibility_wifi_security_type_secured" msgid="2399774097343238942">"ସୁରକ୍ଷିତ ନେଟ୍‌ୱର୍କ"</string>
     <string name="process_kernel_label" msgid="950292573930336765">"Android OS"</string>
     <string name="data_usage_uninstalled_apps" msgid="1933665711856171491">"କଢ଼ାଯାଇଥିବା ଆପ୍‌ଗୁଡ଼ିକ"</string>
-    <string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"ଆପ୍‌ ଏବଂ ଉପଯୋଗକର୍ତ୍ତା ବାହାର କରାଗଲା"</string>
+    <string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"ଆପ୍ସ ଏବଂ ୟୁଜରଙ୍କୁ କାଢ଼ି ଦିଆଯାଇଛି"</string>
     <string name="data_usage_ota" msgid="7984667793701597001">"ସିଷ୍ଟମ୍ ଅପ୍‌ଡେଟ୍"</string>
     <string name="tether_settings_title_usb" msgid="3728686573430917722">"USB ଟିଥରିଂ"</string>
     <string name="tether_settings_title_wifi" msgid="4803402057533895526">"ପୋର୍ଟବଲ୍‌ ହଟସ୍ପଟ୍‌"</string>
@@ -204,7 +207,7 @@
     <string name="tether_settings_title_all" msgid="8910259483383010470">"ଟିଥରିଙ୍ଗ ଓ ପୋର୍ଟବଲ୍ ହଟ୍‌ସ୍ପଟ୍‌"</string>
     <string name="managed_user_title" msgid="449081789742645723">"ସମସ୍ତ କାର୍ଯ୍ୟ ଆପ୍‌"</string>
     <string name="unknown" msgid="3544487229740637809">"ଅଜଣା"</string>
-    <string name="running_process_item_user_label" msgid="3988506293099805796">"ଉପଯୋଗକର୍ତ୍ତା: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
+    <string name="running_process_item_user_label" msgid="3988506293099805796">"ୟୁଜର: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="3631650616557252926">"କିଛି ପୂର୍ବ-ନିର୍ଦ୍ଧାରିତ ମାନ ସେଟ୍‌ ହୋଇଛି"</string>
     <string name="launch_defaults_none" msgid="8049374306261262709">"କୌଣସି ଡିଫଲ୍ଟ ସେଟ୍‍ ହୋଇନାହିଁ"</string>
     <string name="tts_settings" msgid="8130616705989351312">"ଟେକ୍ସଟ୍-ଟୁ-ସ୍ପିଚ୍ ସେଟିଂସ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 64c4e96..73fe924 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"ਬੈਟਰੀ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ਕਿਰਿਆਸ਼ੀਲ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ਕਿਰਿਆਸ਼ੀਲ, ਸਿਰਫ਼ ਖੱਬਾ"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ਕਿਰਿਆਸ਼ੀਲ, ਸਿਰਫ਼ ਸੱਜਾ"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ਕਿਰਿਆਸ਼ੀਲ, ਖੱਬਾ ਅਤੇ ਸੱਜਾ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index d4d27e1..767b87d 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Urządzenie aktywne"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Zapisano"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktywne, tylko lewa strona"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktywne, tylko prawa strona"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktywny, lewa i prawa strona"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 38df760..5bc01f1 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvo"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas o esquerdo"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas o direito"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 9e98623..f0b94bf 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria. <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Guardado"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas esquerdo"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas direito"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 38df760..5bc01f1 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Ativo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvo"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Ativo, apenas o esquerdo"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Ativo, apenas o direito"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Ativo, esquerdo e direito"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index dddc116..4d6638a 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Activ"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Salvat"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Activ, numai stânga"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Activ, numai dreapta"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Activ, stânga și dreapta"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 9a5a400..e155948 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Уровень заряда: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батарея <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активно"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Сохранено"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активен, только левое ухо"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активен, только правое ухо"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активен, оба уха"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 0fce42b..dff692e 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ක්‍රියාකාරී"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"සුරැකිණි"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"සක්‍රිය, වම පමණි"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"සක්‍රිය, දකුණ පමණි"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"සක්‍රිය, වම සහ දකුණ"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 74c9e1f..e85e96d 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batéria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktívne"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Uložené"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktívne, iba ľavá strana"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktívne, iba pravá strana"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktívne, ľavá aj pravá strana"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index a6d35c80..6eb655c 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Baterija na <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktivna"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Shranjeno"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktivno, samo levo"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktivno, samo desno"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktivno, levo in desno"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 3f6e803..f112060 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Bateria <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Të ruajtura"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktive, vetëm majtas"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktive, vetëm djathtas"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktive, majtas dhe djathtas"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 135176b..9341616 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Ниво батерије је <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Батерија, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активан"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Сачувано"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активно, само с леве стране"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активно, с десне стране"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активно, с леве и десне стране"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 7712203..d3370e8 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batteri: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktiv"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Sparad"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktiv, bara vänster"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktiv, bara höger"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktiv, vänster och höger"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 53d583a..d230022 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Chaji ya betri ni <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Kimeunganishwa"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Imeokoa"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Inatumika, kushoto pekee"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Inatumika, kulia pekee"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Inatumika, kushoto na kulia"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index db11263..8097be0 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"பேட்டரி <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"செயலில் உள்ளது"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"சேமிக்கப்பட்டது"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"இடது பக்கம் மட்டும் செயலில் உள்ளது"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"வலது பக்கம் மட்டும் செயலில் உள்ளது"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"வலது மற்றும் இடது பக்கம் செயலில் உள்ளது"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index c2faca9..a9d4c03 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"బ్యాటరీ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"యాక్టివ్‌గా ఉంది"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"సేవ్ చేయబడింది"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"యాక్టివ్‌గా ఉంది, ఎడమవైపు మాత్రమే యాక్టివ్‌గా ఉంది"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"యాక్టివ్‌గా ఉంది, కుడివైపు యాక్టివ్‌గా ఉంది"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"యాక్టివ్‌గా ఉంది, ఎడమవైపు, కుడివైపు యాక్టివ్‌గా ఉంది"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 7b03f81..8f59f36 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"ใช้งานอยู่"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"บันทึกแล้ว"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"ใช้งานอยู่ เฉพาะข้างซ้าย"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"ใช้งานอยู่ เฉพาะข้างขวา"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"ใช้งานอยู่ ข้างซ้ายและขวา"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 8eef17e..58b6e84 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Baterya <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Aktibo"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Na-save"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Aktibo, kaliwa lang"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Aktibo, kanan lang"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Aktibo, kaliwa at kanan"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index cf5bd2d..0300ddc 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Pil düzeyi <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pil <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Etkin"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Kaydedildi"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Yalnızca sol tarafta etkin"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Yalnızca sağ tarafta etkin"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Sol ve sağ tarafta etkin"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 4b40503..807bc51 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Заряд акумулятора: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Активовано"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Збережено"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Активовано, лише лівий"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Активовано, лише правий"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Активовано, лівий і правий"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index a1b2198..cee510b 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"بیٹری <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"فعال"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"محفوظ ہے"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"فعال، صرف بائیں طرف"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"فعال، صرف دائیں طرف"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"فعال، صرف بائیں اور دائیں طرف"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 82f4576..4415667 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Batareya quvvati: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Batareya: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Faol"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Saqlangan"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Faol, faqat chap"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Faol, faqat oʻng"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Faol, chap va oʻng"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 9a1386e..f33d909 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"Mức pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Pin <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Đang hoạt động"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Đã lưu"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Đang hoạt động, chỉ tai bên trái"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Đang hoạt động, chỉ tai phải"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Đang hoạt động, cả tai phải và tai trái"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index d3f8945..816ba8d 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 的电量"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"电池电量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"已保存的设备"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,仅左耳助听器"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,仅右耳助听器"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳助听器"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index b5a1d51..b26efb2 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"已儲存"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,僅左耳"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,僅右耳"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index a131c12..149022c 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"使用中"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"已儲存"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"使用中,僅左耳"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"使用中,僅右耳"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"使用中,左右耳"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index f9bdfbf..7aea126 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -98,9 +98,9 @@
     <skip />
     <!-- no translation found for bluetooth_active_battery_level_untethered (4961338936672922617) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_left (5521405563527657515) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_left (2895644748625343977) -->
     <skip />
-    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7165552824664523336) -->
+    <!-- no translation found for bluetooth_active_battery_level_untethered_right (7407517998880370179) -->
     <skip />
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri"</string>
     <string name="tv_bluetooth_battery_level" msgid="8786353985605532846">"Ibhethri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
@@ -112,9 +112,12 @@
     <skip />
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"Iyasebenza"</string>
     <string name="bluetooth_saved_device" msgid="4895871321722311428">"Ilondoloziwe"</string>
-    <string name="bluetooth_hearing_aid_left_active" msgid="7084887715570971441">"Iyasebenza, ngakwesokunxele kuphela"</string>
-    <string name="bluetooth_hearing_aid_right_active" msgid="8574683234077567230">"Iyasebenza, ngakwesokudla kuphela"</string>
-    <string name="bluetooth_hearing_aid_left_and_right_active" msgid="407704460573163973">"Iyasebenza, ngakwesokunxele nakwesokudla"</string>
+    <!-- no translation found for bluetooth_hearing_aid_left_active (8330226430756799572) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_right_active (2244728507170385397) -->
+    <skip />
+    <!-- no translation found for bluetooth_hearing_aid_left_and_right_active (4294571497939983181) -->
+    <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level (7772517511061834073) -->
     <skip />
     <!-- no translation found for bluetooth_active_media_only_battery_level_untethered (7444753133664620926) -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index fa27db9..dc40304 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -202,8 +202,8 @@
             dreamInfo.componentName = componentName;
             dreamInfo.isActive = dreamInfo.componentName.equals(activeDream);
 
-            final DreamService.DreamMetadata dreamMetadata = DreamService.getDreamMetadata(mContext,
-                    resolveInfo.serviceInfo);
+            final DreamService.DreamMetadata dreamMetadata = DreamService.getDreamMetadata(
+                    mContext.getPackageManager(), resolveInfo.serviceInfo);
             if (dreamMetadata != null) {
                 dreamInfo.settingsComponentName = dreamMetadata.settingsActivity;
                 dreamInfo.previewImage = dreamMetadata.previewImage;
diff --git a/packages/SoundPicker/AndroidManifest.xml b/packages/SoundPicker/AndroidManifest.xml
index 44295a5..98fee5b 100644
--- a/packages/SoundPicker/AndroidManifest.xml
+++ b/packages/SoundPicker/AndroidManifest.xml
@@ -9,6 +9,8 @@
     <uses-permission android:name="android.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
 
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+
     <application
         android:allowBackup="false"
         android:label="@string/app_label"
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/values-bs/strings.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/values-bs/strings.xml
index 749a6f2..199b0c9 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/values-bs/strings.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/values-bs/strings.xml
@@ -9,7 +9,7 @@
     <string name="power_label" msgid="7699720321491287839">"Napajanje"</string>
     <string name="power_utterance" msgid="7444296686402104807">"Opcije napajanja"</string>
     <string name="recent_apps_label" msgid="6583276995616385847">"Nedavne aplikacije"</string>
-    <string name="lockscreen_label" msgid="648347953557887087">"Zaključavanje ekrana"</string>
+    <string name="lockscreen_label" msgid="648347953557887087">"Zaključani ekran"</string>
     <string name="quick_settings_label" msgid="2999117381487601865">"Brze postavke"</string>
     <string name="notifications_label" msgid="6829741046963013567">"Obavještenja"</string>
     <string name="screenshot_label" msgid="863978141223970162">"Snimak ekrana"</string>
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index a51f81f..b3aa7e1 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -532,6 +532,13 @@
 }
 
 flag {
+   name: "smartspace_lockscreen_viewmodel"
+   namespace: "systemui"
+   description: "Indicate Smartspace lockscreen viewmodel"
+   bug: "331451011"
+}
+
+flag {
    name: "pin_input_field_styled_focus_state"
    namespace: "systemui"
    description: "Enables styled focus states on pin input field if keyboard is connected"
@@ -835,3 +842,13 @@
     description: "Enforce BaseUserRestriction for DISALLOW_CONFIG_BRIGHTNESS."
     bug: "329205638"
 }
+
+flag {
+  name: "ambient_touch_monitor_listen_to_display_changes"
+  namespace: "systemui"
+  description: "listen to display changes and cache window metrics"
+  bug: "330906135"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffect.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffect.kt
deleted file mode 100644
index c08afd3..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffect.kt
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.surfaceeffects.gloweffect
-
-import android.animation.ValueAnimator
-import android.animation.ValueAnimator.INFINITE
-import android.graphics.RenderEffect
-import androidx.annotation.VisibleForTesting
-import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
-import com.android.systemui.surfaceeffects.utils.MathUtils
-
-/** Renders rotating pie with glow on top, masked with a rounded box. */
-class GlowPieEffect(
-    config: GlowPieEffectConfig,
-    private val renderEffectDrawCallback: RenderEffectDrawCallback
-) {
-
-    private val glowPieShader = GlowPieShader().apply { applyConfig(config) }
-
-    @VisibleForTesting
-    val mainAnimator: ValueAnimator =
-        ValueAnimator.ofFloat(0f, 1f).apply {
-            // We want to loop the full cycle.
-            duration = DURATION_MS
-            repeatMode = ValueAnimator.RESTART
-            repeatCount = INFINITE
-        }
-
-    /** Plays glow pie until [finish] is called. */
-    fun play() {
-        if (mainAnimator.isRunning) return
-
-        baseGlow.resetProgress()
-        firstGlowPie.resetProgress()
-        secondGlowPie.resetProgress()
-
-        mainAnimator.addUpdateListener { updateListener ->
-            val time = updateListener.currentPlayTime.toFloat() % mainAnimator.duration
-
-            // Remap each glow pie progress.
-            baseGlow.updateProgress(time)
-            firstGlowPie.updateProgress(time)
-            secondGlowPie.updateProgress(time)
-
-            // TODO(b/335315940): Consider passing in 2D Matrix.
-            glowPieShader.setAngles(baseGlow.angle(), firstGlowPie.angle(), secondGlowPie.angle())
-            glowPieShader.setBottomAngleThresholds(
-                baseGlow.bottomThreshold(),
-                firstGlowPie.bottomThreshold(),
-                secondGlowPie.bottomThreshold()
-            )
-            glowPieShader.setTopAngleThresholds(
-                baseGlow.topThreshold(),
-                firstGlowPie.topThreshold(),
-                secondGlowPie.topThreshold()
-            )
-            glowPieShader.setAlphas(baseGlow.alpha(), firstGlowPie.alpha(), secondGlowPie.alpha())
-
-            // Finally trigger the draw callback.
-            renderEffectDrawCallback.onDraw(
-                RenderEffect.createRuntimeShaderEffect(
-                    glowPieShader,
-                    GlowPieShader.BACKGROUND_UNIFORM
-                )
-            )
-        }
-
-        mainAnimator.start()
-    }
-
-    fun finish() {
-        // TODO(b/335315940) Add alpha fade.
-        mainAnimator.cancel()
-    }
-
-    companion object {
-        @VisibleForTesting const val PI = Math.PI.toFloat()
-        @VisibleForTesting const val FEATHER = 0.3f
-        @VisibleForTesting const val DURATION_MS = 3000L
-
-        private val baseGlow = BaseGlow()
-        private val firstGlowPie = FirstGlowPie()
-        private val secondGlowPie = SecondGlowPie()
-    }
-
-    /** Contains animation parameters for each layer of glow pie. */
-    interface GlowPie {
-        /**
-         * The start & end timestamps of the animation. Must be smaller than or equal to the full
-         * [DURATION_MS].
-         */
-        val startMs: Float
-        val endMs: Float
-        /**
-         * Start & end angles in radian. This determines how many cycles you want to rotate. e.g.
-         * startAngle = 0f endAngle = 4f * PI, will give you the 2 cycles.
-         */
-        val startAngle: Float
-        val endAngle: Float
-        /**
-         * Start & end timestamps of the fade out duration. You may want to override [alpha] if you
-         * want to make it fade in. See [BaseGlow].
-         */
-        val alphaFadeStartMs: Float
-        val alphaFadeEndMs: Float
-
-        /** Below two values are expected to be updated through [updateProgress]. */
-        /** Normalized progress. */
-        var progress: Float
-        /** current time of the animation in ms. */
-        var time: Float
-
-        // Must be called before retrieving angle, bottom & top thresholds, and alpha.
-        // Otherwise the values would be stale.
-        fun updateProgress(time: Float) {
-            progress = MathUtils.constrainedMap(0f, 1f, startMs, endMs, time)
-            this.time = time
-        }
-
-        fun resetProgress() {
-            progress = 0f
-            time = 0f
-        }
-
-        fun angle(): Float {
-            // Negate the angle since we want clock-wise rotation.
-            val angle =
-                MathUtils.constrainedMap(startAngle, endAngle, 0f, 1f, progress) + progress * PI
-            return -angle
-        }
-
-        fun bottomThreshold(): Float {
-            return MathUtils.lerp(1f, -FEATHER, progress)
-        }
-
-        fun topThreshold(): Float {
-            return MathUtils.lerp(1f + FEATHER, 0f, progress)
-        }
-
-        // By default, it fades "out".
-        fun alpha(): Float {
-            // Remap timestamps (in MS) to alpha [0, 1].
-            return MathUtils.constrainedMap(1f, 0f, alphaFadeStartMs, alphaFadeEndMs, time)
-        }
-    }
-
-    data class BaseGlow(
-        override val startMs: Float = 0f,
-        override val endMs: Float = 0f,
-        override val startAngle: Float = 0f,
-        override val endAngle: Float = 0f,
-        override val alphaFadeStartMs: Float = 2250f,
-        override val alphaFadeEndMs: Float = 2950f,
-    ) : GlowPie {
-
-        override var progress: Float = 1f
-        override var time: Float = 0f
-        override fun updateProgress(time: Float) {}
-
-        override fun resetProgress() {}
-
-        override fun angle(): Float = 0f
-
-        override fun bottomThreshold(): Float = 0f
-
-        override fun topThreshold(): Float = 0f
-
-        // Base glow fade "in" (i.e. reveals).
-        override fun alpha(): Float {
-            return MathUtils.constrainedMap(0f, 1f, alphaFadeStartMs, alphaFadeEndMs, time)
-        }
-    }
-
-    data class FirstGlowPie(
-        override val startMs: Float = 250f,
-        override val endMs: Float = 2500f,
-        override val startAngle: Float = -PI / 2f,
-        override val endAngle: Float = 4f * PI,
-        override val alphaFadeStartMs: Float = 2500f,
-        override val alphaFadeEndMs: Float = 2750f,
-        override var progress: Float = 0f,
-        override var time: Float = 0f
-    ) : GlowPie
-
-    data class SecondGlowPie(
-        override val startMs: Float = 350f,
-        override val endMs: Float = 2600f,
-        override val startAngle: Float = -PI / 2f,
-        override val endAngle: Float = 3f * PI,
-        override val alphaFadeStartMs: Float = 2600f,
-        override val alphaFadeEndMs: Float = 2850f,
-        override var progress: Float = 0f,
-        override var time: Float = 0f
-    ) : GlowPie
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectConfig.kt
deleted file mode 100644
index 6c728c1..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectConfig.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.surfaceeffects.gloweffect
-
-/** Parameter values needed to draw [GlowPieEffect]. */
-data class GlowPieEffectConfig(
-    /** Center x position of the effect. */
-    val centerX: Float,
-    /** Center y position of the effect. */
-    val centerY: Float,
-    /** Width of the rounded box mask. */
-    val width: Float,
-    /** Height of the rounded box mask. */
-    val height: Float,
-    /** Corner radius of the rounded box mask. */
-    val cornerRadius: Float,
-    /**
-     * Colors of the effect. The number must match 3, which is defined in [GlowPieShader.NUM_PIE].
-     * Each color corresponds to baseColor (bottom), firstLayerColor, and secondLayerColor (top).
-     */
-    val colors: IntArray
-)
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieShader.kt
deleted file mode 100644
index 2dbc0b5..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieShader.kt
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.surfaceeffects.gloweffect
-
-import android.graphics.RuntimeShader
-import android.util.Log
-import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary
-import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
-
-/** Draws two glowing pies rotating around the center of a rounded box on a base. */
-class GlowPieShader : RuntimeShader(GLOW_PIE_SHADER_COMP) {
-    // language=AGSL
-    companion object {
-        const val BACKGROUND_UNIFORM = "in_dst"
-        const val NUM_PIE = 3
-
-        private const val UNIFORMS =
-            """
-            uniform shader ${BACKGROUND_UNIFORM};
-            uniform vec2 in_center;
-            uniform vec2 in_size;
-            uniform half in_cornerRad;
-            uniform float[${NUM_PIE}] in_angles;
-            uniform float[${NUM_PIE}] in_alphas;
-            uniform float[${NUM_PIE}] in_bottomThresholds;
-            uniform float[${NUM_PIE}] in_topThresholds;
-            layout(color) uniform vec4 in_colors0;
-            layout(color) uniform vec4 in_colors1;
-            layout(color) uniform vec4 in_colors2;
-        """
-
-        private const val GLOW_PIE_MAIN =
-            """
-        vec4 main(vec2 p) {
-            vec4 pie = vec4(0.);
-            vec4 glow = vec4(0.);
-
-            vec2 c = p - in_center;
-            half box = sdRoundedBox(c, in_size, in_cornerRad);
-
-            // Base glow (drawn at the bottom)
-            pieGlow(
-                box,
-                c,
-                in_angles[0],
-                in_colors0.rgb,
-                /* pieAlpha= */ 1., // We always show the base color.
-                /* glowAlpha= */ in_alphas[0],
-                vec2(in_bottomThresholds[0], in_topThresholds[0]),
-                pie,
-                glow
-            );
-
-            // First pie
-            pieGlow(
-                box,
-                c,
-                in_angles[1],
-                in_colors1.rgb,
-                /* pieAlpha= */ in_alphas[1],
-                /* glowAlpha= */ in_alphas[1],
-                vec2(in_bottomThresholds[1], in_topThresholds[1]),
-                pie,
-                glow
-            );
-
-            // Second pie (drawn on top)
-            pieGlow(
-                box,
-                c,
-                in_angles[2],
-                in_colors2.rgb,
-                /* pieAlpha= */ in_alphas[2],
-                /* glowAlpha= */ in_alphas[2],
-                vec2(in_bottomThresholds[2], in_topThresholds[2]),
-                pie,
-                glow
-            );
-
-            return vec4(pie.rgb + glow.rgb * 0.3, pie.a);
-        }
-        """
-
-        private const val REMAP =
-            """
-            float remap(float in_start, float in_end, float out_start, float out_end, float x) {
-                x = (x - in_start) / (in_end - in_start);
-                x = clamp(x, 0., 1.);
-                return x * (out_end - out_start) + out_start;
-            }
-        """
-
-        /**
-         * This function draws a pie slice, an a glow on top. The glow also has the same pie shape
-         * but with more blur and additive blending.
-         */
-        private const val GLOW_PIE =
-            """
-            void pieGlow(
-                half box,
-                vec2 c,
-                half angle,
-                vec3 color,
-                half pieAlpha,
-                half glowAlpha,
-                vec2 angleThresholds,
-                inout vec4 inout_pie,
-                inout vec4 inout_glow) {
-
-                // Apply angular rotation.
-                half co = cos(angle), si = sin(angle);
-                mat2 rotM = mat2(co, -si, si, co); // 2D rotation matrix
-                c *= rotM;
-
-                // We rotate based on the cosine value, since we want to avoid using inverse
-                // trig function, which in this case is atan.
-
-                // Dot product with vec2(1., 0.) and bring the range to [0,1].
-                // Same as dot(normalize(c), vec2(1.,0) * 0.5 + 0.5
-                half d = normalize(c).x * 0.5 + 0.5;
-
-                // Those thresholds represents each end of the pie.
-                float bottomThreshold = angleThresholds[0];
-                float topThreshold = angleThresholds[1];
-                float angleMask = remap(bottomThreshold, topThreshold, 0., 1., d);
-
-                half boxMask = 1. - smoothstep(-0.02, 0.02, box);
-                vec4 pie = vec4(color, 1.0) * angleMask * boxMask * pieAlpha;
-
-                // We are drawing the same pie but with more blur.
-                half glowMask = 1. - smoothstep(0., 0.6, box);
-                // Glow outside only.
-                glowMask = min(glowMask, smoothstep(-0.02, 0.02, box));
-                // Apply some curve for the glow. (Can take out)
-                glowMask *= glowMask * glowMask;
-                // Glow mask should also be sliced with the angle mask.
-                glowMask *= angleMask;
-                vec4 glow = vec4(color, 1.0) * glowMask * glowAlpha;
-
-                inout_pie = pie + inout_pie * (1. - pie.a);
-                // Additive blending.
-                inout_glow += glow;
-            }
-            """
-
-        private const val GLOW_PIE_SHADER_COMP =
-            ShaderUtilLibrary.SHADER_LIB +
-                SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
-                SdfShaderLibrary.ROUNDED_BOX_SDF +
-                UNIFORMS +
-                REMAP +
-                GLOW_PIE +
-                GLOW_PIE_MAIN
-
-        private val TAG = GlowPieShader::class.java.simpleName
-    }
-
-    fun applyConfig(config: GlowPieEffectConfig) {
-        setCenter(config.centerX, config.centerY)
-        setSize(config.width, config.height)
-        setCornerRadius(config.cornerRadius)
-        setColor(config.colors)
-    }
-
-    fun setCenter(centerX: Float, centerY: Float) {
-        setFloatUniform("in_center", centerX, centerY)
-    }
-
-    fun setSize(width: Float, height: Float) {
-        setFloatUniform("in_size", width, height)
-    }
-
-    fun setCornerRadius(cornerRadius: Float) {
-        setFloatUniform("in_cornerRad", cornerRadius)
-    }
-
-    /** Ignores alpha value, as fade in/out is handled within shader. */
-    fun setColor(colors: IntArray) {
-        if (colors.size != NUM_PIE) {
-            Log.wtf(TAG, "The number of colors must be $NUM_PIE")
-            return
-        }
-        setColorUniform("in_colors0", colors[0])
-        setColorUniform("in_colors1", colors[1])
-        setColorUniform("in_colors2", colors[2])
-    }
-
-    fun setAngles(vararg angles: Float) {
-        if (angles.size != NUM_PIE) {
-            Log.wtf(TAG, "The number of angles must be $NUM_PIE")
-            return
-        }
-        setFloatUniform("in_angles", angles)
-    }
-
-    fun setAlphas(vararg alphas: Float) {
-        if (alphas.size != NUM_PIE) {
-            Log.wtf(TAG, "The number of angles must be $NUM_PIE")
-            return
-        }
-        setFloatUniform("in_alphas", alphas)
-    }
-
-    fun setBottomAngleThresholds(vararg bottomThresholds: Float) {
-        if (bottomThresholds.size != NUM_PIE) {
-            Log.wtf(TAG, "The number of bottomThresholds must be $NUM_PIE")
-            return
-        }
-        setFloatUniform("in_bottomThresholds", bottomThresholds)
-    }
-
-    fun setTopAngleThresholds(vararg topThresholds: Float) {
-        if (topThresholds.size != NUM_PIE) {
-            Log.wtf(TAG, "The number of topThresholds must be $NUM_PIE")
-            return
-        }
-        setFloatUniform("in_topThresholds", topThresholds)
-    }
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffect.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffect.kt
deleted file mode 100644
index ffa2b46..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffect.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.surfaceeffects.revealeffect
-
-import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.ValueAnimator
-import android.graphics.RenderEffect
-import androidx.core.graphics.ColorUtils
-import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
-import com.android.systemui.surfaceeffects.utils.MathUtils
-import kotlin.math.max
-import kotlin.math.min
-
-/** Creates a reveal effect with a circular ripple sparkles on top. */
-class RippleRevealEffect(
-    private val config: RippleRevealEffectConfig,
-    private val renderEffectCallback: RenderEffectDrawCallback,
-    private val stateChangedCallback: AnimationStateChangedCallback? = null
-) {
-    private val rippleRevealShader = RippleRevealShader().apply { applyConfig(config) }
-    private val animator: ValueAnimator = ValueAnimator.ofFloat(0f, 1f)
-
-    fun play() {
-        if (animator.isRunning) {
-            return
-        }
-
-        animator.duration = config.duration.toLong()
-        animator.addUpdateListener { updateListener ->
-            val playTime = updateListener.currentPlayTime.toFloat()
-            rippleRevealShader.setTime(playTime * TIME_SCALE_FACTOR)
-
-            // Compute radius.
-            val progress = updateListener.animatedValue as Float
-            val innerRad = MathUtils.lerp(config.innerRadiusStart, config.innerRadiusEnd, progress)
-            val outerRad = MathUtils.lerp(config.outerRadiusStart, config.outerRadiusEnd, progress)
-            rippleRevealShader.setInnerRadius(innerRad)
-            rippleRevealShader.setOuterRadius(outerRad)
-
-            // Compute alphas.
-            val innerAlphaProgress =
-                MathUtils.constrainedMap(
-                    1f,
-                    0f,
-                    config.innerFadeOutStart,
-                    config.duration,
-                    playTime
-                )
-            val outerAlphaProgress =
-                MathUtils.constrainedMap(
-                    1f,
-                    0f,
-                    config.outerFadeOutStart,
-                    config.duration,
-                    playTime
-                )
-            val innerAlpha = MathUtils.lerp(0f, 255f, innerAlphaProgress)
-            val outerAlpha = MathUtils.lerp(0f, 255f, outerAlphaProgress)
-
-            val innerColor = ColorUtils.setAlphaComponent(config.innerColor, innerAlpha.toInt())
-            val outerColor = ColorUtils.setAlphaComponent(config.outerColor, outerAlpha.toInt())
-            rippleRevealShader.setInnerColor(innerColor)
-            rippleRevealShader.setOuterColor(outerColor)
-
-            // Pass in progresses since those functions take in normalized alpha values.
-            rippleRevealShader.setBackgroundAlpha(max(innerAlphaProgress, outerAlphaProgress))
-            rippleRevealShader.setSparkleAlpha(min(innerAlphaProgress, outerAlphaProgress))
-
-            // Trigger draw callback.
-            renderEffectCallback.onDraw(
-                RenderEffect.createRuntimeShaderEffect(
-                    rippleRevealShader,
-                    RippleRevealShader.BACKGROUND_UNIFORM
-                )
-            )
-        }
-        animator.addListener(
-            object : AnimatorListenerAdapter() {
-                override fun onAnimationEnd(animation: Animator) {
-                    stateChangedCallback?.onAnimationEnd()
-                }
-            }
-        )
-        animator.start()
-        stateChangedCallback?.onAnimationStart()
-    }
-
-    interface AnimationStateChangedCallback {
-        fun onAnimationStart()
-        fun onAnimationEnd()
-    }
-
-    private companion object {
-        private const val TIME_SCALE_FACTOR = 0.00175f
-    }
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectConfig.kt
deleted file mode 100644
index 9675f19..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectConfig.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.surfaceeffects.revealeffect
-
-import android.graphics.Color
-
-/** Defines parameters needed for [RippleRevealEffect]. */
-data class RippleRevealEffectConfig(
-    /** Total duration of the animation. */
-    val duration: Float = 0f,
-    /** Timestamp of when the inner mask starts fade out. (Linear fadeout) */
-    val innerFadeOutStart: Float = 0f,
-    /** Timestamp of when the outer mask starts fade out. (Linear fadeout) */
-    val outerFadeOutStart: Float = 0f,
-    /** Center x position of the effect. */
-    val centerX: Float = 0f,
-    /** Center y position of the effect. */
-    val centerY: Float = 0f,
-    /** Start radius of the inner circle. */
-    val innerRadiusStart: Float = 0f,
-    /** End radius of the inner circle. */
-    val innerRadiusEnd: Float = 0f,
-    /** Start radius of the outer circle. */
-    val outerRadiusStart: Float = 0f,
-    /** End radius of the outer circle. */
-    val outerRadiusEnd: Float = 0f,
-    /**
-     * Pixel density of the display. Do not pass a random value. The value must come from
-     * [context.resources.displayMetrics.density].
-     */
-    val pixelDensity: Float = 1f,
-    /**
-     * The amount the circle masks should be softened. Higher value will make the edge of the circle
-     * mask soft.
-     */
-    val blurAmount: Float = 0f,
-    /** Color of the inner circle mask. */
-    val innerColor: Int = Color.WHITE,
-    /** Color of the outer circle mask. */
-    val outerColor: Int = Color.WHITE,
-    /** Multiplier to make the sparkles visible. */
-    val sparkleStrength: Float = SPARKLE_STRENGTH,
-    /** Size of the sparkle. Expected range [0, 1]. */
-    val sparkleScale: Float = SPARKLE_SCALE
-) {
-    /** Default parameters. */
-    companion object {
-        const val SPARKLE_STRENGTH: Float = 0.3f
-        const val SPARKLE_SCALE: Float = 0.8f
-    }
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealShader.kt
deleted file mode 100644
index a3f9795..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealShader.kt
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.surfaceeffects.revealeffect
-
-import android.graphics.RuntimeShader
-import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary
-import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
-
-/** Circular reveal effect with sparkles. */
-class RippleRevealShader : RuntimeShader(SHADER) {
-    // language=AGSL
-    companion object {
-        const val BACKGROUND_UNIFORM = "in_dst"
-        private const val MAIN =
-            """
-            uniform shader ${BACKGROUND_UNIFORM};
-            uniform half in_dstAlpha;
-            uniform half in_time;
-            uniform vec2 in_center;
-            uniform half in_innerRadius;
-            uniform half in_outerRadius;
-            uniform half in_sparkleStrength;
-            uniform half in_blur;
-            uniform half in_pixelDensity;
-            uniform half in_sparkleScale;
-            uniform half in_sparkleAlpha;
-            layout(color) uniform vec4 in_innerColor;
-            layout(color) uniform vec4 in_outerColor;
-
-            vec4 main(vec2 p) {
-                half innerMask = soften(sdCircle(p - in_center, in_innerRadius), in_blur);
-                half outerMask = soften(sdCircle(p - in_center, in_outerRadius), in_blur);
-
-                // Flip it since we are interested in the circle.
-                innerMask = 1.-innerMask;
-                outerMask = 1.-outerMask;
-
-                // Color two circles using the mask.
-                vec4 inColor = vec4(in_innerColor.rgb, 1.) * in_innerColor.a;
-                vec4 outColor = vec4(in_outerColor.rgb, 1.) * in_outerColor.a;
-                vec4 blend = mix(inColor, outColor, innerMask);
-
-                vec4 dst = vec4(in_dst.eval(p).rgb, 1.);
-                dst *= in_dstAlpha;
-
-                blend *= blend.a;
-                // Do normal blend with the background.
-                blend = blend + dst * (1. - blend.a);
-
-                half sparkle =
-                    sparkles(p - mod(p, in_pixelDensity * in_sparkleScale), in_time);
-                // Add sparkles using additive blending.
-                blend += sparkle * in_sparkleStrength * in_sparkleAlpha;
-
-                // Mask everything at the end.
-                blend *= outerMask;
-
-                return blend;
-            }
-        """
-
-        private const val SHADER =
-            ShaderUtilLibrary.SHADER_LIB +
-                SdfShaderLibrary.SHADER_SDF_OPERATION_LIB +
-                SdfShaderLibrary.CIRCLE_SDF +
-                MAIN
-    }
-
-    fun applyConfig(config: RippleRevealEffectConfig) {
-        setCenter(config.centerX, config.centerY)
-        setInnerRadius(config.innerRadiusStart)
-        setOuterRadius(config.outerRadiusStart)
-        setBlurAmount(config.blurAmount)
-        setPixelDensity(config.pixelDensity)
-        setSparkleScale(config.sparkleScale)
-        setSparkleStrength(config.sparkleStrength)
-        setInnerColor(config.innerColor)
-        setOuterColor(config.outerColor)
-    }
-
-    fun setTime(time: Float) {
-        setFloatUniform("in_time", time)
-    }
-
-    fun setCenter(centerX: Float, centerY: Float) {
-        setFloatUniform("in_center", centerX, centerY)
-    }
-
-    fun setInnerRadius(radius: Float) {
-        setFloatUniform("in_innerRadius", radius)
-    }
-
-    fun setOuterRadius(radius: Float) {
-        setFloatUniform("in_outerRadius", radius)
-    }
-
-    fun setBlurAmount(blurAmount: Float) {
-        setFloatUniform("in_blur", blurAmount)
-    }
-
-    fun setPixelDensity(density: Float) {
-        setFloatUniform("in_pixelDensity", density)
-    }
-
-    fun setSparkleScale(scale: Float) {
-        setFloatUniform("in_sparkleScale", scale)
-    }
-
-    fun setSparkleStrength(strength: Float) {
-        setFloatUniform("in_sparkleStrength", strength)
-    }
-
-    fun setInnerColor(color: Int) {
-        setColorUniform("in_innerColor", color)
-    }
-
-    fun setOuterColor(color: Int) {
-        setColorUniform("in_outerColor", color)
-    }
-
-    /** Sets the background alpha. Range [0,1]. */
-    fun setBackgroundAlpha(alpha: Float) {
-        setFloatUniform("in_dstAlpha", alpha)
-    }
-
-    /** Sets the sparkle alpha. Range [0,1]. */
-    fun setSparkleAlpha(alpha: Float) {
-        setFloatUniform("in_sparkleAlpha", alpha)
-    }
-}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/utils/MathUtils.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/utils/MathUtils.kt
deleted file mode 100644
index 1411c32..0000000
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/utils/MathUtils.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.surfaceeffects.utils
-
-/** Copied from android.utils.MathUtils */
-object MathUtils {
-    fun constrainedMap(
-        rangeMin: Float,
-        rangeMax: Float,
-        valueMin: Float,
-        valueMax: Float,
-        value: Float
-    ): Float {
-        return lerp(rangeMin, rangeMax, lerpInvSat(valueMin, valueMax, value))
-    }
-
-    fun lerp(start: Float, stop: Float, amount: Float): Float {
-        return start + (stop - start) * amount
-    }
-
-    fun lerpInv(a: Float, b: Float, value: Float): Float {
-        return if (a != b) (value - a) / (b - a) else 0.0f
-    }
-
-    fun saturate(value: Float): Float {
-        return constrain(value, 0.0f, 1.0f)
-    }
-
-    fun lerpInvSat(a: Float, b: Float, value: Float): Float {
-        return saturate(lerpInv(a, b, value))
-    }
-
-    fun constrain(amount: Float, low: Float, high: Float): Float {
-        return if (amount < low) low else if (amount > high) high else amount
-    }
-}
diff --git a/packages/SystemUI/checks/Android.bp b/packages/SystemUI/checks/Android.bp
index 1f502e3..addcaf4 100644
--- a/packages/SystemUI/checks/Android.bp
+++ b/packages/SystemUI/checks/Android.bp
@@ -39,7 +39,7 @@
     srcs: ["tests/**/*.kt"],
     data: [
         ":framework",
-        ":androidx.annotation_annotation-nodeps",
+        ":androidx.annotation_annotation",
         ":kotlinx-coroutines-core",
     ],
     static_libs: [
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
index edfd59a..e1cca88 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
@@ -22,7 +22,7 @@
 internal val libraryNames =
     arrayOf(
         "framework.jar",
-        "androidx.annotation_annotation-nodeps.jar",
+        "androidx.annotation_annotation.jar",
         "kotlinx-coroutines-core.jar",
     )
 
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
index 19d6038..7af8408 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PatternBouncer.kt
@@ -52,7 +52,6 @@
 import com.android.internal.R
 import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.PatternDotViewModel
-import kotlin.math.max
 import kotlin.math.min
 import kotlin.math.pow
 import kotlin.math.sqrt
@@ -110,30 +109,14 @@
         remember(dots) {
             dots.associateWith { dot -> with(density) { (80 + (20 * dot.y)).dp.toPx() } }
         }
-    val dotAppearScaleAnimatables = remember(dots) { dots.associateWith { Animatable(0f) } }
     LaunchedEffect(Unit) {
         dotAppearFadeInAnimatables.forEach { (dot, animatable) ->
             scope.launch {
-                // Maps a dot at x and y to an ordinal number to denote the order in which all dots
-                // are visited by the fade-in animation.
-                //
-                // The order is basically starting from the top-left most dot (at 0,0) and ending at
-                // the bottom-right most dot (at 2,2). The visitation order happens
-                // diagonal-by-diagonal. Here's a visual representation of the expected output:
-                // [0][1][3]
-                // [2][4][6]
-                // [5][7][8]
-                //
-                // There's an assumption here that the grid is 3x3. If it's not, this formula needs
-                // to be revisited.
-                check(viewModel.columnCount == 3 && viewModel.rowCount == 3)
-                val staggerOrder = max(0, min(8, 2 * (dot.x + dot.y) + (dot.y - 1)))
-
                 animatable.animateTo(
                     targetValue = 1f,
                     animationSpec =
                         tween(
-                            delayMillis = 33 * staggerOrder,
+                            delayMillis = 33 * dot.y,
                             durationMillis = 450,
                             easing = Easings.LegacyDecelerate,
                         )
@@ -153,19 +136,6 @@
                 )
             }
         }
-        dotAppearScaleAnimatables.forEach { (dot, animatable) ->
-            scope.launch {
-                animatable.animateTo(
-                    targetValue = 1f,
-                    animationSpec =
-                        tween(
-                            delayMillis = 33 * dot.y,
-                            durationMillis = 450,
-                            easing = Easings.LegacyDecelerate,
-                        )
-                )
-            }
-        }
     }
 
     val view = LocalView.current
@@ -401,10 +371,7 @@
                         ),
                     color =
                         dotColor.copy(alpha = checkNotNull(dotAppearFadeInAnimatables[dot]).value),
-                    radius =
-                        dotRadius *
-                            checkNotNull(dotScalingAnimatables[dot]).value *
-                            checkNotNull(dotAppearScaleAnimatables[dot]).value,
+                    radius = dotRadius * checkNotNull(dotScalingAnimatables[dot]).value
                 )
             }
         }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 89d4343..338987a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -132,6 +132,7 @@
 import com.android.systemui.communal.ui.viewmodel.BaseCommunalViewModel
 import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
+import com.android.systemui.communal.ui.viewmodel.PopupType
 import com.android.systemui.communal.widgets.WidgetConfigurator
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.phone.SystemUIDialogFactory
@@ -148,8 +149,7 @@
     onEditDone: (() -> Unit)? = null,
 ) {
     val communalContent by viewModel.communalContent.collectAsState(initial = emptyList())
-    val isPopupOnDismissCtaShowing by
-        viewModel.isPopupOnDismissCtaShowing.collectAsState(initial = false)
+    val currentPopup by viewModel.currentPopup.collectAsState(initial = null)
     var removeButtonCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) }
     var toolbarSize: IntSize? by remember { mutableStateOf(null) }
     var gridCoordinates: LayoutCoordinates? by remember { mutableStateOf(null) }
@@ -161,7 +161,6 @@
     val removeButtonEnabled by remember {
         derivedStateOf { selectedKey.value != null || reorderingWidgets }
     }
-    var isButtonToEditWidgetsShowing by remember { mutableStateOf(false) }
     val isEmptyState by viewModel.isEmptyState.collectAsState(initial = false)
 
     val contentPadding = gridContentPadding(viewModel.isEditMode, toolbarSize)
@@ -214,7 +213,7 @@
                                         communalContent[index] is
                                             CommunalContentModel.CtaTileInViewMode
                                 ) {
-                                    isButtonToEditWidgetsShowing = true
+                                    viewModel.onShowCustomizeWidgetButton()
                                 }
                                 val key =
                                     index?.let { keyAtIndexIfEditable(communalContent, index) }
@@ -290,18 +289,22 @@
             )
         }
 
-        if (isPopupOnDismissCtaShowing) {
-            PopupOnDismissCtaTile(viewModel::onHidePopupAfterDismissCta)
-        }
-
-        if (isButtonToEditWidgetsShowing) {
-            ButtonToEditWidgets(
-                onClick = {
-                    isButtonToEditWidgetsShowing = false
-                    viewModel.onOpenWidgetEditor(selectedKey.value)
-                },
-                onHide = { isButtonToEditWidgetsShowing = false },
-            )
+        if (currentPopup != null) {
+            when (currentPopup) {
+                PopupType.CtaTile -> {
+                    PopupOnDismissCtaTile(viewModel::onHidePopup)
+                }
+                PopupType.CustomizeWidgetButton -> {
+                    ButtonToEditWidgets(
+                        onClick = {
+                            viewModel.onHidePopup()
+                            viewModel.onOpenWidgetEditor(selectedKey.value)
+                        },
+                        onHide = { viewModel.onHidePopup()}
+                    )
+                }
+                null -> {}
+            }
         }
 
         if (viewModel is CommunalViewModel && dialogFactory != null) {
@@ -679,11 +682,11 @@
 }
 
 @Composable
-private fun PopupOnDismissCtaTile(onHidePopupAfterDismissCta: () -> Unit) {
+private fun PopupOnDismissCtaTile(onHidePopup: () -> Unit) {
     Popup(
         alignment = Alignment.TopCenter,
         offset = IntOffset(0, 40),
-        onDismissRequest = onHidePopupAfterDismissCta
+        onDismissRequest = onHidePopup
     ) {
         val colors = LocalAndroidColorScheme.current
         Row(
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index fc32440..f6575dc 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -78,9 +78,9 @@
 import com.android.systemui.shade.ui.composable.Shade
 import com.android.systemui.shade.ui.composable.ShadeHeader
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
-import com.android.systemui.statusbar.phone.StatusBarIconController
-import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager
 import com.android.systemui.statusbar.phone.StatusBarLocation
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController
+import com.android.systemui.statusbar.phone.ui.TintedIconManager
 import javax.inject.Inject
 import kotlin.math.roundToInt
 import kotlinx.coroutines.CoroutineScope
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
index 516e140..d3b3d15 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
@@ -69,10 +69,10 @@
 import com.android.systemui.shade.ui.composable.ShadeHeader.Dimensions.CollapsedHeight
 import com.android.systemui.shade.ui.composable.ShadeHeader.Values.ClockScale
 import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
-import com.android.systemui.statusbar.phone.StatusBarIconController
-import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager
 import com.android.systemui.statusbar.phone.StatusBarLocation
 import com.android.systemui.statusbar.phone.StatusIconContainer
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController
+import com.android.systemui.statusbar.phone.ui.TintedIconManager
 import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernShadeCarrierGroupMobileView
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.ShadeCarrierGroupMobileIconViewModel
 import com.android.systemui.statusbar.policy.Clock
@@ -372,6 +372,20 @@
             val batteryIcon = BatteryMeterView(context, null)
             batteryIcon.setPercentShowMode(BatteryMeterView.MODE_ON)
 
+            val themedContext =
+                ContextThemeWrapper(context, R.style.Theme_SystemUI_QuickSettings_Header)
+            val fg = Utils.getColorAttrDefaultColor(themedContext, android.R.attr.textColorPrimary)
+            val bg =
+                Utils.getColorAttrDefaultColor(
+                    themedContext,
+                    android.R.attr.textColorPrimaryInverse,
+                )
+
+            // [BatteryMeterView.updateColors] is an old method that was built to distinguish
+            // between dual-tone colors and single-tone. The current icon is only single-tone, so
+            // the final [fg] is the only one we actually need
+            batteryIcon.updateColors(fg, bg, fg)
+
             val batteryMaterViewController =
                 createBatteryMeterViewController(batteryIcon, StatusBarLocation.QS)
             batteryMaterViewController.init()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 944d6ef..91a9d2a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -82,9 +82,9 @@
 import com.android.systemui.scene.ui.composable.ComposableScene
 import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.shade.ui.viewmodel.ShadeSceneViewModel
-import com.android.systemui.statusbar.phone.StatusBarIconController
-import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager
 import com.android.systemui.statusbar.phone.StatusBarLocation
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController
+import com.android.systemui.statusbar.phone.ui.TintedIconManager
 import com.android.systemui.util.animation.MeasurementInput
 import javax.inject.Inject
 import javax.inject.Named
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index a595c66..f78ed2f 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -658,12 +658,28 @@
         targetOffset: Float,
         targetScene: SceneKey,
     ): OffsetAnimation {
+        // Skip the animation if we have already reached the target scene and the overscroll does
+        // not animate anything.
+        val hasReachedTargetScene =
+            (targetScene == toScene && progress >= 1f) ||
+                (targetScene == fromScene && progress <= 0f)
+        val skipAnimation =
+            hasReachedTargetScene &&
+                currentOverscrollSpec?.transformationSpec?.transformations?.isEmpty() == true
+
         return startOffsetAnimation {
             val animatable = Animatable(dragOffset, OffsetVisibilityThreshold)
             val isTargetGreater = targetOffset > animatable.value
             val job =
                 coroutineScope
                     .launch {
+                        // TODO(b/327249191): Refactor the code so that we don't even launch a
+                        // coroutine if we don't need to animate.
+                        if (skipAnimation) {
+                            snapToScene(targetScene)
+                            return@launch
+                        }
+
                         try {
                             val swipeSpec =
                                 transformationSpec.swipeSpec
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 2ed51eb..1fd1bf4 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -1007,4 +1007,23 @@
         dragController.onDragStopped(velocity = 0f)
         assertTransition(isUserInputOngoing = false)
     }
+
+    @Test
+    fun emptyOverscrollImmediatelyAbortsSettleAnimationWhenOverProgress() = runGestureTest {
+        // Overscrolling on scene B does nothing.
+        layoutState.transitions = transitions { overscroll(SceneB, Orientation.Vertical) {} }
+
+        // Swipe up to scene B at progress = 200%.
+        val middle = Offset(SCREEN_SIZE / 2f, SCREEN_SIZE / 2f)
+        val dragController = onDragStarted(startedPosition = middle, overSlop = up(2f))
+        assertTransition(fromScene = SceneA, toScene = SceneB, progress = 2f)
+
+        // Release the finger.
+        dragController.onDragStopped(velocity = -velocityThreshold)
+
+        // Exhaust all coroutines *without advancing the clock*. Given that we are at progress >=
+        // 100% and that the overscroll on scene B is doing nothing, we are already idle.
+        runCurrent()
+        assertIdle(SceneB)
+    }
 }
diff --git a/packages/SystemUI/docs/scene.md b/packages/SystemUI/docs/scene.md
index f331c9b..fb8a271 100644
--- a/packages/SystemUI/docs/scene.md
+++ b/packages/SystemUI/docs/scene.md
@@ -65,23 +65,25 @@
 [`SceneContainerFlags.kt`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt)
 file evalutes to `true`.
 
-1.  Set the **`migrate_keyguard_status_bar_view`** classic flag to `true` by
-    running: `console $ adb shell statusbar cmd migrate_keyguard_status_bar_view
-    true`
-2.  Set a collection of **aconfig flags** to `true` by running the following
+1.  Set a collection of **aconfig flags** to `true` by running the following
     commands:
     ```console
-    $ adb shell device_config put systemui com.android.systemui.scene_container true
-    $ adb shell device_config put systemui com.android.systemui.compose_lockscreen true
-    $ adb shell device_config put systemui com.android.systemui.keyguard_bottom_area_refactor true
-    $ adb shell device_config put systemui com.android.systemui.media_in_scene_container true
-    $ adb shell device_config put systemui com.android.systemui.migrate_clocks_to_blueprint true
+    $ adb shell device_config override systemui com.android.systemui.scene_container true
+    $ adb shell device_config override systemui com.android.systemui.compose_lockscreen true
+    $ adb shell device_config override systemui com.android.systemui.keyguard_bottom_area_refactor true
+    $ adb shell device_config override systemui com.android.systemui.keyguard_wm_state_refactor true
+    $ adb shell device_config override systemui com.android.systemui.media_in_scene_container true
+    $ adb shell device_config override systemui com.android.systemui.migrate_clocks_to_blueprint true
+    $ adb shell device_config override systemui com.android.systemui.notification_heads_up_refactor true
+    $ adb shell device_config override systemui com.android.systemui.predictive_back_sysui true
+    $ adb shell device_config override systemui com.android.systemui.device_entry_udfps_refactor true
+    $ adb shell device_config override systemui com.android.systemui.refactor_keyguard_dismiss_intent true
     ```
-3.  **Restart** System UI by issuing the following command:
+2.  **Restart** System UI by issuing the following command:
     ```console
     $ adb shell am crash com.android.systemui
     ```
-4.  **Verify** that the scene framework was turned on. There are two ways to do
+3.  **Verify** that the scene framework was turned on. There are two ways to do
     this:
 
     *(a)* look for the sash/ribbon UI at the bottom-right corner of the display:
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/Shades.java b/packages/SystemUI/monet/src/com/android/systemui/monet/Shades.java
index c97b960..c8b9fe0 100644
--- a/packages/SystemUI/monet/src/com/android/systemui/monet/Shades.java
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/Shades.java
@@ -21,7 +21,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.ColorUtils;
 
-
 /**
  * Generate sets of colors that are shades of the same color
  */
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
index fefe5a0..3395268 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
@@ -66,6 +66,7 @@
 
 import java.util.Collections;
 import java.util.Optional;
+
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 9b0b5de..f3de463e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -118,6 +118,8 @@
 
 import dagger.Lazy;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -132,8 +134,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import kotlinx.coroutines.CoroutineScope;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 @RunWithLooper(setAsMainLooper = true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index b83c0ce..ecfcc90 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneContainerStartable
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
 import com.android.systemui.testKosmos
@@ -67,10 +68,13 @@
     private val testScope = kosmos.testScope
     private val authenticationInteractor by lazy { kosmos.authenticationInteractor }
     private val bouncerInteractor by lazy { kosmos.bouncerInteractor }
+    private val sceneContainerStartable = kosmos.sceneContainerStartable
+
     private lateinit var underTest: BouncerViewModel
 
     @Before
     fun setUp() {
+        sceneContainerStartable.start()
         underTest = kosmos.bouncerViewModel
     }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index 779e79ed..c96a8ce 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -20,9 +20,9 @@
 import android.appwidget.AppWidgetProviderInfo
 import android.content.pm.UserInfo
 import android.os.UserHandle
+import android.platform.test.flag.junit.FlagsParameterization
 import android.provider.Settings
 import android.widget.RemoteViews
-import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
 import com.android.systemui.SysuiTestCase
@@ -38,9 +38,11 @@
 import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel.Companion.POPUP_AUTO_HIDE_TIMEOUT_MS
+import com.android.systemui.communal.ui.viewmodel.PopupType
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
+import com.android.systemui.flags.andSceneContainer
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -50,8 +52,9 @@
 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
 import com.android.systemui.media.controls.ui.view.MediaHost
 import com.android.systemui.settings.fakeUserTracker
-import com.android.systemui.shade.data.repository.fakeShadeRepository
+import com.android.systemui.shade.ShadeTestUtil
 import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.shadeTestUtil
 import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository
 import com.android.systemui.smartspace.data.repository.fakeSmartspaceRepository
 import com.android.systemui.testKosmos
@@ -70,11 +73,13 @@
 import org.mockito.Mockito
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
-@RunWith(AndroidJUnit4::class)
-class CommunalViewModelTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class CommunalViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {
     @Mock private lateinit var mediaHost: MediaHost
     @Mock private lateinit var user: UserInfo
     @Mock private lateinit var providerInfo: AppWidgetProviderInfo
@@ -88,9 +93,14 @@
     private lateinit var smartspaceRepository: FakeSmartspaceRepository
     private lateinit var mediaRepository: FakeCommunalMediaRepository
     private lateinit var userRepository: FakeUserRepository
+    private lateinit var shadeTestUtil: ShadeTestUtil
 
     private lateinit var underTest: CommunalViewModel
 
+    init {
+        mSetFlagsRule.setFlagsParameterization(flags!!)
+    }
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -101,6 +111,7 @@
         smartspaceRepository = kosmos.fakeSmartspaceRepository
         mediaRepository = kosmos.fakeCommunalMediaRepository
         userRepository = kosmos.fakeUserRepository
+        shadeTestUtil = kosmos.shadeTestUtil
 
         kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true)
         mSetFlagsRule.enableFlags(FLAG_COMMUNAL_HUB)
@@ -237,7 +248,7 @@
             tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED)
 
             val communalContent by collectLastValue(underTest.communalContent)
-            val isPopupOnDismissCtaShowing by collectLastValue(underTest.isPopupOnDismissCtaShowing)
+            val currentPopup by collectLastValue(underTest.currentPopup)
 
             assertThat(communalContent?.size).isEqualTo(1)
             assertThat(communalContent?.get(0))
@@ -247,11 +258,11 @@
 
             // hide CTA tile and show the popup
             assertThat(communalContent).isEmpty()
-            assertThat(isPopupOnDismissCtaShowing).isEqualTo(true)
+            assertThat(currentPopup).isEqualTo(PopupType.CtaTile)
 
             // hide popup after time elapsed
             advanceTimeBy(POPUP_AUTO_HIDE_TIMEOUT_MS)
-            assertThat(isPopupOnDismissCtaShowing).isEqualTo(false)
+            assertThat(currentPopup).isNull()
         }
 
     @Test
@@ -259,14 +270,40 @@
         testScope.runTest {
             tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED)
 
-            val isPopupOnDismissCtaShowing by collectLastValue(underTest.isPopupOnDismissCtaShowing)
+            val currentPopup by collectLastValue(underTest.currentPopup)
 
             underTest.onDismissCtaTile()
-            assertThat(isPopupOnDismissCtaShowing).isEqualTo(true)
+            assertThat(currentPopup).isEqualTo(PopupType.CtaTile)
 
             // dismiss the popup directly
-            underTest.onHidePopupAfterDismissCta()
-            assertThat(isPopupOnDismissCtaShowing).isEqualTo(false)
+            underTest.onHidePopup()
+            assertThat(currentPopup).isNull()
+        }
+
+    @Test
+    fun customizeWidgetButton_showsThenHidesAfterTimeout() =
+        testScope.runTest {
+            tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED)
+            val currentPopup by collectLastValue(underTest.currentPopup)
+
+            assertThat(currentPopup).isNull()
+            underTest.onShowCustomizeWidgetButton()
+            assertThat(currentPopup).isEqualTo(PopupType.CustomizeWidgetButton)
+            advanceTimeBy(POPUP_AUTO_HIDE_TIMEOUT_MS)
+            assertThat(currentPopup).isNull()
+        }
+
+    @Test
+    fun customizeWidgetButton_onDismiss_hidesImmediately() =
+        testScope.runTest {
+            tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED)
+            val currentPopup by collectLastValue(underTest.currentPopup)
+
+            underTest.onShowCustomizeWidgetButton()
+            assertThat(currentPopup).isEqualTo(PopupType.CustomizeWidgetButton)
+
+            underTest.onHidePopup()
+            assertThat(currentPopup).isNull()
         }
 
     @Test
@@ -274,7 +311,7 @@
         testScope.runTest {
             // On keyguard without any shade expansion.
             kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
-            kosmos.fakeShadeRepository.setLockscreenShadeExpansion(0f)
+            shadeTestUtil.setLockscreenShadeExpansion(0f)
             runCurrent()
             assertThat(underTest.canChangeScene()).isTrue()
         }
@@ -284,7 +321,7 @@
         testScope.runTest {
             // On keyguard with shade fully expanded.
             kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
-            kosmos.fakeShadeRepository.setLockscreenShadeExpansion(1f)
+            shadeTestUtil.setLockscreenShadeExpansion(1f)
             runCurrent()
             assertThat(underTest.canChangeScene()).isFalse()
         }
@@ -297,5 +334,11 @@
 
     private companion object {
         val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
+
+        @JvmStatic
+        @Parameters(name = "{0}")
+        fun getParams(): List<FlagsParameterization> {
+            return FlagsParameterization.allCombinationsOf().andSceneContainer()
+        }
     }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index 6b2a1d5..e9dc261 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -654,7 +654,7 @@
         }
 
     @Test
-    fun authenticateFallbacksToDetectionWhenUserIsAlreadyTrustedByTrustManager() =
+    fun authenticateFallbacksToDetectionWhenKeyguardIsAlreadyDismissible() =
         testScope.runTest {
             whenever(faceManager.sensorPropertiesInternal)
                 .thenReturn(listOf(createFaceSensorProperties(supportsFaceDetection = true)))
@@ -663,7 +663,7 @@
             initCollectors()
             allPreconditionsToRunFaceAuthAreTrue()
 
-            trustRepository.setCurrentUserTrusted(true)
+            keyguardRepository.setKeyguardDismissible(true)
             assertThat(canFaceAuthRun()).isFalse()
             underTest.requestAuthenticate(
                 FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index e2e5169..2b3f40f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -49,6 +49,8 @@
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
 import com.android.systemui.statusbar.BlurUtils;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -56,8 +58,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import kotlinx.coroutines.CoroutineDispatcher;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 @RunWithLooper(setAsMainLooper = true)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
index bdb0c9a..eef2337 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
@@ -17,6 +17,9 @@
 
 import android.content.ComponentName
 import android.content.Intent
+import android.os.RemoteException
+import android.platform.test.annotations.EnableFlags
+import android.service.dreams.Flags
 import android.service.dreams.IDreamOverlay
 import android.service.dreams.IDreamOverlayCallback
 import android.service.dreams.IDreamOverlayClient
@@ -44,7 +47,9 @@
 import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
 import com.android.systemui.communal.data.repository.FakeCommunalRepository
 import com.android.systemui.communal.data.repository.fakeCommunalRepository
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
 import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.communal.domain.interactor.setCommunalAvailable
 import com.android.systemui.communal.shared.model.CommunalScenes
 import com.android.systemui.complication.ComplicationHostViewController
 import com.android.systemui.complication.ComplicationLayoutEngine
@@ -57,12 +62,14 @@
 import com.android.systemui.touch.TouchInsetManager
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.whenever
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -70,6 +77,9 @@
 import org.mockito.Captor
 import org.mockito.Mock
 import org.mockito.Mockito
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.isNull
+import org.mockito.Mockito.spy
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
@@ -87,6 +97,8 @@
 
     private lateinit var lifecycleRegistry: FakeLifecycleRegistry
 
+    lateinit var mCommunalInteractor: CommunalInteractor
+
     private lateinit var mWindowParams: WindowManager.LayoutParams
 
     @Mock lateinit var mDreamOverlayCallback: IDreamOverlayCallback
@@ -162,6 +174,9 @@
         whenever(mComplicationComponent.getComplicationHostViewController())
             .thenReturn(mComplicationHostViewController)
         whenever(mLifecycleOwner.registry).thenReturn(lifecycleRegistry)
+
+        mCommunalInteractor = Mockito.spy(kosmos.communalInteractor)
+
         whenever(mComplicationComponentFactory.create(any(), any(), any(), any()))
             .thenReturn(mComplicationComponent)
         whenever(mComplicationComponent.getVisibilityController())
@@ -192,7 +207,7 @@
                 mStateController,
                 mKeyguardUpdateMonitor,
                 mScrimManager,
-                kosmos.communalInteractor,
+                mCommunalInteractor,
                 mSystemDialogsCloser,
                 mUiEventLogger,
                 mTouchInsetManager,
@@ -605,6 +620,57 @@
             .isTrue()
     }
 
+    @Test
+    @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT)
+    @kotlin.Throws(RemoteException::class)
+    fun testTransitionToGlanceableHub() =
+        testScope.runTest {
+            // Inform the overlay service of dream starting. Do not show dream complications.
+            client.startDream(
+                mWindowParams,
+                mDreamOverlayCallback,
+                DREAM_COMPONENT,
+                false /*shouldShowComplication*/
+            )
+            mMainExecutor.runAllReady()
+
+            verify(mDreamOverlayCallback).onRedirectWake(false)
+            clearInvocations(mDreamOverlayCallback)
+            kosmos.setCommunalAvailable(true)
+            mMainExecutor.runAllReady()
+            runCurrent()
+            verify(mDreamOverlayCallback).onRedirectWake(true)
+            client.onWakeRequested()
+            verify(mCommunalInteractor).changeScene(eq(CommunalScenes.Communal), isNull())
+        }
+
+    @Test
+    @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT)
+    @Throws(RemoteException::class)
+    fun testRedirectExit() =
+        testScope.runTest {
+            // Inform the overlay service of dream starting. Do not show dream complications.
+            client.startDream(
+                mWindowParams,
+                mDreamOverlayCallback,
+                DREAM_COMPONENT,
+                false /*shouldShowComplication*/
+            )
+            // Set communal available, verify that overlay callback is informed.
+            kosmos.setCommunalAvailable(true)
+            mMainExecutor.runAllReady()
+            runCurrent()
+            verify(mDreamOverlayCallback).onRedirectWake(true)
+
+            clearInvocations(mDreamOverlayCallback)
+
+            // Set communal unavailable, verify that overlay callback is informed.
+            kosmos.setCommunalAvailable(false)
+            mMainExecutor.runAllReady()
+            runCurrent()
+            verify(mDreamOverlayCallback).onRedirectWake(false)
+        }
+
     // Tests that the bouncer closes when DreamOverlayService is told that the dream is coming to
     // the front.
     @Test
@@ -689,6 +755,31 @@
             )
     }
 
+    // Verifies that the touch handling lifecycle is STARTED even if the dream starts while not
+    // focused.
+    @Test
+    fun testLifecycle_dreamNotFocusedOnStart_isStarted() {
+        val transitionState: MutableStateFlow<ObservableTransitionState> =
+            MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank))
+        communalRepository.setTransitionState(transitionState)
+
+        // Communal becomes visible.
+        transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)
+        testScope.runCurrent()
+        mMainExecutor.runAllReady()
+
+        // Start dreaming.
+        val client = client
+        client.startDream(
+            mWindowParams,
+            mDreamOverlayCallback,
+            DREAM_COMPONENT,
+            false /*shouldShowComplication*/
+        )
+        mMainExecutor.runAllReady()
+        assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.STARTED)
+    }
+
     @Test
     fun testLifecycle_destroyedAfterOnDestroy() {
         val client = client
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
index cb5702ad..ccadd14 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
@@ -31,6 +31,8 @@
 import com.android.systemui.assist.AssistManager.VisualQueryAttentionListener;
 import com.android.systemui.shared.condition.Condition;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -38,8 +40,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import kotlinx.coroutines.CoroutineScope;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 @android.platform.test.annotations.EnabledOnRavenwood
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
index 96d3c93..58c17e2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
@@ -34,6 +34,8 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.shared.condition.Condition;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -41,8 +43,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import kotlinx.coroutines.CoroutineScope;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 @android.platform.test.annotations.EnabledOnRavenwood
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
index e332656..c51413a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/qs/QSLongPressEffectTest.kt
@@ -21,7 +21,6 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.animation.AnimatorTestRule
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.haptics.vibratorHelper
 import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -32,19 +31,14 @@
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
-import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
 @RunWithLooper(setAsMainLooper = true)
 class QSLongPressEffectTest : SysuiTestCase() {
 
-    @Rule @JvmField val mMockitoRule: MockitoRule = MockitoJUnit.rule()
-    @get:Rule val animatorTestRule = AnimatorTestRule(this)
     private val kosmos = testKosmos()
     private val vibratorHelper = kosmos.vibratorHelper
 
@@ -67,58 +61,28 @@
                 vibratorHelper,
                 kosmos.keyguardInteractor,
             )
-        longPressEffect.initializeEffect(effectDuration)
     }
 
     @Test
-    fun onReset_whileIdle_resetsEffect() = testWithScope {
-        // GIVEN a call to reset
-        longPressEffect.resetEffect()
+    fun onInitialize_withNegativeDuration_doesNotInitialize() =
+        testWithScope(false) {
+            // WHEN attempting to initialize with a negative duration
+            val couldInitialize = longPressEffect.initializeEffect(-1)
 
-        // THEN the effect remains idle and has not been initialized
-        val state by collectLastValue(longPressEffect.state)
-        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
-        assertThat(longPressEffect.hasInitialized).isFalse()
-    }
-
-    @Test
-    fun onReset_whileRunning_resetsEffect() = testWhileRunning {
-        // GIVEN a call to reset
-        longPressEffect.resetEffect()
-
-        // THEN the effect remains idle and has not been initialized
-        val state by collectLastValue(longPressEffect.state)
-        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
-        assertThat(longPressEffect.hasInitialized).isFalse()
-    }
-
-    @Test
-    fun onInitialize_withNegativeDuration_doesNotInitialize() = testWithScope {
-        // GIVEN an effect that has reset
-        longPressEffect.resetEffect()
-
-        // WHEN attempting to initialize with a negative duration
-        val couldInitialize = longPressEffect.initializeEffect(-1)
-
-        // THEN the effect can't initialized and remains reset
-        val state by collectLastValue(longPressEffect.state)
-        assertThat(couldInitialize).isFalse()
-        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
-        assertThat(longPressEffect.hasInitialized).isFalse()
-    }
+            // THEN the effect can't initialized and remains reset
+            assertThat(couldInitialize).isFalse()
+            assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
+            assertThat(longPressEffect.hasInitialized).isFalse()
+        }
 
     @Test
     fun onInitialize_withPositiveDuration_initializes() = testWithScope {
-        // GIVEN an effect that has reset
-        longPressEffect.resetEffect()
-
         // WHEN attempting to initialize with a positive duration
         val couldInitialize = longPressEffect.initializeEffect(effectDuration)
 
         // THEN the effect is initialized
-        val state by collectLastValue(longPressEffect.state)
         assertThat(couldInitialize).isTrue()
-        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
+        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
         assertThat(longPressEffect.hasInitialized).isTrue()
     }
 
@@ -128,140 +92,174 @@
         longPressEffect.handleActionDown()
 
         // THEN the effect moves to the TIMEOUT_WAIT state
-        val state by collectLastValue(longPressEffect.state)
-        assertThat(state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
+        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
     }
 
     @Test
-    fun onActionCancel_whileWaiting_goesIdle() = testWhileWaiting {
-        // GIVEN an action cancel occurs
-        longPressEffect.handleActionCancel()
+    fun onActionCancel_whileWaiting_goesIdle() =
+        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
+            // GIVEN an action cancel occurs
+            longPressEffect.handleActionCancel()
 
-        // THEN the effect goes back to idle and does not start
-        val state by collectLastValue(longPressEffect.state)
-        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
-        assertEffectDidNotStart()
+            // THEN the effect goes back to idle and does not start
+            assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
+            assertEffectDidNotStart()
+        }
+
+    @Test
+    fun onActionUp_whileWaiting_performsClick() =
+        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
+            // GIVEN an action is being collected
+            val action by collectLastValue(longPressEffect.actionType)
+
+            // GIVEN an action up occurs
+            longPressEffect.handleActionUp()
+
+            // THEN the action to invoke is the click action and the effect does not start
+            assertThat(action).isEqualTo(QSLongPressEffect.ActionType.CLICK)
+            assertEffectDidNotStart()
+        }
+
+    @Test
+    fun onWaitComplete_whileWaiting_beginsEffect() =
+        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
+            // GIVEN the pressed timeout is complete
+            longPressEffect.handleTimeoutComplete()
+
+            // THEN the effect emits the action to start an animator
+            val action by collectLastValue(longPressEffect.actionType)
+            assertThat(action).isEqualTo(QSLongPressEffect.ActionType.START_ANIMATOR)
+        }
+
+    @Test
+    fun onAnimationStart_whileWaiting_effectBegins() =
+        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
+            // GIVEN that the animator starts
+            longPressEffect.handleAnimationStart()
+
+            // THEN the effect begins
+            assertEffectStarted()
+        }
+
+    @Test
+    fun onActionUp_whileEffectHasBegun_reversesEffect() =
+        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
+            // GIVEN an action up occurs
+            longPressEffect.handleActionUp()
+
+            // THEN the effect reverses
+            assertEffectReverses()
+        }
+
+    @Test
+    fun onPlayReverseHaptics_reverseHapticsArePlayed() = testWithScope {
+        // GIVEN a call to play reverse haptics at the effect midpoint
+        val progress = 0.5f
+        longPressEffect.playReverseHaptics(progress)
+
+        // THEN the expected texture is played
+        val reverseHaptics =
+            LongPressHapticBuilder.createReversedEffect(
+                progress,
+                lowTickDuration,
+                effectDuration,
+            )
+        assertThat(reverseHaptics).isNotNull()
+        assertThat(vibratorHelper.hasVibratedWithEffects(reverseHaptics!!)).isTrue()
     }
 
     @Test
-    fun onActionUp_whileWaiting_performsClick() = testWhileWaiting {
-        // GIVEN an action is being collected
-        val action by collectLastValue(longPressEffect.actionType)
+    fun onActionCancel_whileEffectHasBegun_reversesEffect() =
+        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
+            // WHEN an action cancel occurs
+            longPressEffect.handleActionCancel()
 
-        // GIVEN an action up occurs
-        longPressEffect.handleActionUp()
-
-        // THEN the action to invoke is the click action and the effect does not start
-        assertThat(action).isEqualTo(QSLongPressEffect.ActionType.CLICK)
-        assertEffectDidNotStart()
-    }
+            // THEN the effect gets reversed
+            assertEffectReverses()
+        }
 
     @Test
-    fun onWaitComplete_whileWaiting_beginsEffect() = testWhileWaiting {
-        // GIVEN the pressed timeout is complete
-        longPressEffect.handleTimeoutComplete()
+    fun onAnimationComplete_keyguardDismissible_effectEndsWithLongPress() =
+        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
+            // GIVEN that the animation completes
+            longPressEffect.handleAnimationComplete()
 
-        // THEN the effect starts
-        assertEffectStarted()
-    }
-
-    @Test
-    fun onActionUp_whileEffectHasBegun_reversesEffect() = testWhileRunning {
-        // GIVEN that the effect is at the middle of its completion (progress of 50%)
-        animatorTestRule.advanceTimeBy(effectDuration / 2L)
-
-        // WHEN an action up occurs
-        longPressEffect.handleActionUp()
-
-        // THEN the effect gets reversed at 50% progress
-        assertEffectReverses(0.5f)
-    }
-
-    @Test
-    fun onActionCancel_whileEffectHasBegun_reversesEffect() = testWhileRunning {
-        // GIVEN that the effect is at the middle of its completion (progress of 50%)
-        animatorTestRule.advanceTimeBy(effectDuration / 2L)
-
-        // WHEN an action cancel occurs
-        longPressEffect.handleActionCancel()
-
-        // THEN the effect gets reversed at 50% progress
-        assertEffectReverses(0.5f)
-    }
-
-    @Test
-    fun onAnimationComplete_keyguardDismissible_effectEndsWithLongPress() = testWhileRunning {
-        // GIVEN that the animation completes
-        animatorTestRule.advanceTimeBy(effectDuration + 10L)
-
-        // THEN the long-press effect completes with a LONG_PRESS
-        assertEffectCompleted(QSLongPressEffect.ActionType.LONG_PRESS)
-    }
+            // THEN the long-press effect completes with a LONG_PRESS
+            assertEffectCompleted(QSLongPressEffect.ActionType.LONG_PRESS)
+        }
 
     @Test
     fun onAnimationComplete_keyguardNotDismissible_effectEndsWithResetAndLongPress() =
-        testWhileRunning {
+        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
             // GIVEN that the keyguard is not dismissible
             kosmos.fakeKeyguardRepository.setKeyguardDismissible(false)
 
             // GIVEN that the animation completes
-            animatorTestRule.advanceTimeBy(effectDuration + 10L)
+            longPressEffect.handleAnimationComplete()
 
             // THEN the long-press effect completes with RESET_AND_LONG_PRESS
             assertEffectCompleted(QSLongPressEffect.ActionType.RESET_AND_LONG_PRESS)
         }
 
     @Test
-    fun onActionDown_whileRunningBackwards_resets() = testWhileRunning {
-        // GIVEN that the effect is at the middle of its completion (progress of 50%)
-        animatorTestRule.advanceTimeBy(effectDuration / 2L)
+    fun onActionDown_whileRunningBackwards_cancels() =
+        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
+            // GIVEN an action cancel occurs and the effect gets reversed
+            longPressEffect.handleActionCancel()
 
-        // GIVEN an action cancel occurs and the effect gets reversed
-        longPressEffect.handleActionCancel()
+            // GIVEN an action down occurs
+            longPressEffect.handleActionDown()
 
-        // GIVEN an action down occurs
-        longPressEffect.handleActionDown()
-
-        // THEN the effect resets
-        assertEffectResets()
-    }
+            // THEN the effect posts an action to cancel the animator
+            val action by collectLastValue(longPressEffect.actionType)
+            assertThat(action).isEqualTo(QSLongPressEffect.ActionType.CANCEL_ANIMATOR)
+        }
 
     @Test
-    fun onAnimationComplete_whileRunningBackwards_goesToIdle() = testWhileRunning {
-        // GIVEN that the effect is at the middle of its completion (progress of 50%)
-        animatorTestRule.advanceTimeBy(effectDuration / 2L)
+    fun onAnimatorCancel_effectGoesBackToWait() =
+        testWhileInState(QSLongPressEffect.State.RUNNING_FORWARD) {
+            // GIVEN that the animator was cancelled
+            longPressEffect.handleAnimationCancel()
 
-        // GIVEN an action cancel occurs and the effect gets reversed
-        longPressEffect.handleActionCancel()
+            // THEN the state goes to the timeout wait
+            assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
+        }
 
-        // GIVEN that the animation completes after a sufficient amount of time
-        animatorTestRule.advanceTimeBy(effectDuration.toLong())
+    @Test
+    fun onAnimationComplete_whileRunningBackwards_goesToIdle() =
+        testWhileInState(QSLongPressEffect.State.RUNNING_BACKWARDS) {
+            // GIVEN an action cancel occurs and the effect gets reversed
+            longPressEffect.handleActionCancel()
 
-        // THEN the state goes to [QSLongPressEffect.State.IDLE]
-        val state by collectLastValue(longPressEffect.state)
-        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
-    }
+            // GIVEN that the animation completes
+            longPressEffect.handleAnimationComplete()
 
-    private fun testWithScope(test: suspend TestScope.() -> Unit) =
-        with(kosmos) { testScope.runTest { test() } }
+            // THEN the state goes to [QSLongPressEffect.State.IDLE]
+            assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
+        }
 
-    private fun testWhileWaiting(test: suspend TestScope.() -> Unit) =
+    private fun testWithScope(initialize: Boolean = true, test: suspend TestScope.() -> Unit) =
         with(kosmos) {
             testScope.runTest {
-                // GIVEN the TIMEOUT_WAIT state is entered
-                longPressEffect.setState(QSLongPressEffect.State.TIMEOUT_WAIT)
-
-                // THEN run the test
+                if (initialize) {
+                    longPressEffect.initializeEffect(effectDuration)
+                }
                 test()
             }
         }
 
-    private fun testWhileRunning(test: suspend TestScope.() -> Unit) =
+    private fun testWhileInState(
+        state: QSLongPressEffect.State,
+        initialize: Boolean = true,
+        test: suspend TestScope.() -> Unit,
+    ) =
         with(kosmos) {
             testScope.runTest {
-                // GIVEN that the effect starts after the tap timeout is complete
-                longPressEffect.setState(QSLongPressEffect.State.TIMEOUT_WAIT)
-                longPressEffect.handleTimeoutComplete()
+                if (initialize) {
+                    longPressEffect.initializeEffect(effectDuration)
+                }
+                // GIVEN a state
+                longPressEffect.setState(state)
 
                 // THEN run the test
                 test()
@@ -270,13 +268,10 @@
 
     /**
      * Asserts that the effect started by checking that:
-     * 1. The effect progress is 0f
-     * 2. Initial hint haptics are played
-     * 3. The internal state is [QSLongPressEffect.State.RUNNING_FORWARD]
+     * 1. Initial hint haptics are played
+     * 2. The internal state is [QSLongPressEffect.State.RUNNING_FORWARD]
      */
-    private fun TestScope.assertEffectStarted() {
-        val effectProgress by collectLastValue(longPressEffect.effectProgress)
-        val state by collectLastValue(longPressEffect.state)
+    private fun assertEffectStarted() {
         val longPressHint =
             LongPressHapticBuilder.createLongPressHint(
                 lowTickDuration,
@@ -284,78 +279,48 @@
                 effectDuration,
             )
 
-        assertThat(state).isEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
-        assertThat(effectProgress).isEqualTo(0f)
+        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
         assertThat(longPressHint).isNotNull()
         assertThat(vibratorHelper.hasVibratedWithEffects(longPressHint!!)).isTrue()
     }
 
     /**
      * Asserts that the effect did not start by checking that:
-     * 1. No effect progress is emitted
-     * 2. No haptics are played
-     * 3. The internal state is not [QSLongPressEffect.State.RUNNING_BACKWARDS] or
+     * 1. No haptics are played
+     * 2. The internal state is not [QSLongPressEffect.State.RUNNING_BACKWARDS] or
      *    [QSLongPressEffect.State.RUNNING_FORWARD]
      */
-    private fun TestScope.assertEffectDidNotStart() {
-        val effectProgress by collectLastValue(longPressEffect.effectProgress)
-        val state by collectLastValue(longPressEffect.state)
-
-        assertThat(state).isNotEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
-        assertThat(state).isNotEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
-        assertThat(effectProgress).isNull()
+    private fun assertEffectDidNotStart() {
+        assertThat(longPressEffect.state).isNotEqualTo(QSLongPressEffect.State.RUNNING_FORWARD)
+        assertThat(longPressEffect.state).isNotEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
         assertThat(vibratorHelper.totalVibrations).isEqualTo(0)
     }
 
     /**
      * Asserts that the effect completes by checking that:
-     * 1. The progress is null
-     * 2. The final snap haptics are played
-     * 3. The internal state goes back to [QSLongPressEffect.State.IDLE]
-     * 4. The action to perform on the tile is the action given as a parameter
+     * 1. The final snap haptics are played
+     * 2. The internal state goes back to [QSLongPressEffect.State.IDLE]
+     * 3. The action to perform on the tile is the action given as a parameter
      */
     private fun TestScope.assertEffectCompleted(expectedAction: QSLongPressEffect.ActionType) {
         val action by collectLastValue(longPressEffect.actionType)
-        val effectProgress by collectLastValue(longPressEffect.effectProgress)
         val snapEffect = LongPressHapticBuilder.createSnapEffect()
-        val state by collectLastValue(longPressEffect.state)
 
-        assertThat(effectProgress).isNull()
         assertThat(snapEffect).isNotNull()
         assertThat(vibratorHelper.hasVibratedWithEffects(snapEffect!!)).isTrue()
-        assertThat(state).isEqualTo(QSLongPressEffect.State.IDLE)
+        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
         assertThat(action).isEqualTo(expectedAction)
     }
 
     /**
      * Assert that the effect gets reverted by checking that:
      * 1. The internal state is [QSLongPressEffect.State.RUNNING_BACKWARDS]
-     * 2. The reverse haptics plays at the point where the animation was paused
+     * 2. An action to reverse the animator is emitted
      */
-    private fun TestScope.assertEffectReverses(pausedProgress: Float) {
-        val reverseHaptics =
-            LongPressHapticBuilder.createReversedEffect(
-                pausedProgress,
-                lowTickDuration,
-                effectDuration,
-            )
-        val state by collectLastValue(longPressEffect.state)
+    private fun TestScope.assertEffectReverses() {
+        val action by collectLastValue(longPressEffect.actionType)
 
-        assertThat(state).isEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
-        assertThat(reverseHaptics).isNotNull()
-        assertThat(vibratorHelper.hasVibratedWithEffects(reverseHaptics!!)).isTrue()
-    }
-
-    /**
-     * Asserts that the effect resets by checking that:
-     * 1. The effect progress resets to 0
-     * 2. The internal state goes back to [QSLongPressEffect.State.TIMEOUT_WAIT]
-     */
-    private fun TestScope.assertEffectResets() {
-        val effectProgress by collectLastValue(longPressEffect.effectProgress)
-        val state by collectLastValue(longPressEffect.state)
-
-        assertThat(effectProgress).isNull()
-        assertThat(state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
+        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.RUNNING_BACKWARDS)
+        assertThat(action).isEqualTo(QSLongPressEffect.ActionType.REVERSE_ANIMATOR)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
similarity index 92%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
index 6f17c55..d702330 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorTest.kt
@@ -36,7 +36,6 @@
 import android.platform.test.annotations.EnableFlags
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
-import com.android.internal.widget.lockPatternUtils
 import com.android.systemui.Flags
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
@@ -54,16 +53,15 @@
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.testKosmos
-import com.android.systemui.util.mockito.whenever
 import junit.framework.Assert.assertEquals
-import kotlin.test.Test
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.advanceTimeBy
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
+import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mockito.reset
 import org.mockito.Mockito.spy
 
@@ -93,6 +91,7 @@
         // Transition to AOD and set the power interactor asleep.
         powerInteractor.setAsleepForTest()
         runBlocking {
+            kosmos.fakeKeyguardRepository.setKeyguardShowing(false)
             transitionRepository.sendTransitionSteps(
                 from = KeyguardState.LOCKSCREEN,
                 to = KeyguardState.AOD,
@@ -108,7 +107,7 @@
     fun testTransitionToLockscreen_onWakeup() =
         testScope.runTest {
             powerInteractor.setAwakeForTest()
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
             // Under default conditions, we should transition to LOCKSCREEN when waking up.
             assertThat(transitionRepository)
@@ -124,7 +123,7 @@
         testScope.runTest {
             kosmos.keyguardOcclusionRepository.setShowWhenLockedActivityInfo(true)
             powerInteractor.setAwakeForTest()
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
             // Waking with a SHOW_WHEN_LOCKED activity on top should transition to OCCLUDED.
             assertThat(transitionRepository)
@@ -140,7 +139,7 @@
         testScope.runTest {
             powerInteractor.onCameraLaunchGestureDetected()
             powerInteractor.setAwakeForTest()
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
             // We should head back to GONE since we started there.
             assertThat(transitionRepository)
@@ -154,7 +153,7 @@
             kosmos.fakeKeyguardRepository.setKeyguardDismissible(true)
             powerInteractor.onCameraLaunchGestureDetected()
             powerInteractor.setAwakeForTest()
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
             // We should head back to GONE since we started there.
             assertThat(transitionRepository)
@@ -191,7 +190,7 @@
             reset(transitionRepository)
             powerInteractor.onCameraLaunchGestureDetected()
             powerInteractor.setAwakeForTest()
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
             // We should head back to GONE since we started there.
             assertThat(transitionRepository)
@@ -225,7 +224,7 @@
             reset(transitionRepository)
             powerInteractor.onCameraLaunchGestureDetected()
             powerInteractor.setAwakeForTest()
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
             // We should go to OCCLUDED - we came from GONE, but we finished in AOD, so this is no
             // longer an insecure camera launch and it would be bad if we unlocked now.
@@ -266,7 +265,7 @@
             reset(transitionRepository)
             powerInteractor.onCameraLaunchGestureDetected()
             powerInteractor.setAwakeForTest()
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
             // We should head back to GONE since we started there.
             assertThat(transitionRepository)
@@ -286,7 +285,7 @@
             assertThat(transitionRepository).noTransitionsStarted()
 
             underTest.dismissAod()
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
             assertThat(transitionRepository)
                 .startedTransition(from = KeyguardState.AOD, to = KeyguardState.GONE)
@@ -297,7 +296,7 @@
         testScope.runTest {
             kosmos.fakeKeyguardRepository.setKeyguardOccluded(true)
             powerInteractor.setAwakeForTest()
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
             // Waking up from AOD while occluded should transition to OCCLUDED.
             assertThat(transitionRepository)
@@ -307,11 +306,10 @@
     @Test
     fun testTransitionToGone_onWakeUpFromAod_dismissibleKeyguard_securityNone() =
         testScope.runTest {
-            whenever(kosmos.lockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(true)
+            kosmos.fakeKeyguardRepository.setKeyguardShowing(false)
             kosmos.fakeKeyguardRepository.setKeyguardDismissible(true)
             powerInteractor.setAwakeForTest()
-            testScope.testScheduler.advanceTimeBy(100) // account for debouncing
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
             // We should head back to GONE since we started there.
             assertThat(transitionRepository)
@@ -319,15 +317,13 @@
         }
 
     @Test
-    fun testTransitionToGone_onWakeUpFromAod_dismissibleKeyguard_securitySwipe() =
+    fun testTransitionToLockscreen_onWakeUpFromAod_dismissibleKeyguard_securitySwipe() =
         testScope.runTest {
-            whenever(kosmos.lockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false)
+            kosmos.fakeKeyguardRepository.setKeyguardShowing(true)
             kosmos.fakeKeyguardRepository.setKeyguardDismissible(true)
             powerInteractor.setAwakeForTest()
-            testScope.testScheduler.advanceTimeBy(100) // account for debouncing
-            runCurrent()
+            advanceTimeBy(100) // account for debouncing
 
-            // We should head back to GONE since we started there.
             assertThat(transitionRepository)
                 .startedTransition(from = KeyguardState.AOD, to = KeyguardState.LOCKSCREEN)
         }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index 719828c..d2a458c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -29,6 +29,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
 import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
@@ -38,6 +39,8 @@
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
 import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
 import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.sceneBackInteractor
+import com.android.systemui.scene.domain.interactor.sceneContainerStartable
 import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel
@@ -58,6 +61,7 @@
 
 @SmallTest
 @RunWith(AndroidJUnit4::class)
+@EnableSceneContainer
 class QuickSettingsSceneViewModelTest : SysuiTestCase() {
 
     private val kosmos = testKosmos()
@@ -71,6 +75,8 @@
     private val footerActionsController = mock<FooterActionsController>()
 
     private val sceneInteractor = kosmos.sceneInteractor
+    private val sceneBackInteractor = kosmos.sceneBackInteractor
+    private val sceneContainerStartable = kosmos.sceneContainerStartable
 
     private lateinit var underTest: QuickSettingsSceneViewModel
 
@@ -79,6 +85,7 @@
     fun setUp() {
         kosmos.fakeFeatureFlagsClassic.set(Flags.NEW_NETWORK_SLICE_UI, false)
 
+        sceneContainerStartable.start()
         underTest =
             QuickSettingsSceneViewModel(
                 applicationScope = testScope.backgroundScope,
@@ -89,7 +96,7 @@
                 notifications = kosmos.notificationsPlaceholderViewModel,
                 footerActionsViewModelFactory = footerActionsViewModelFactory,
                 footerActionsController = footerActionsController,
-                sceneInteractor = sceneInteractor,
+                sceneBackInteractor = sceneBackInteractor,
             )
     }
 
@@ -127,11 +134,12 @@
             val destinations by collectLastValue(underTest.destinationScenes)
 
             val currentScene by collectLastValue(sceneInteractor.currentScene)
-            val previousScene by collectLastValue(sceneInteractor.previousScene())
+            val backScene by collectLastValue(sceneBackInteractor.backScene)
             sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
             sceneInteractor.changeScene(Scenes.QuickSettings, "reason")
             assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
-            assertThat(previousScene).isEqualTo(Scenes.Lockscreen)
+            assertThat(backScene).isEqualTo(Scenes.Lockscreen)
+
             assertThat(destinations)
                 .isEqualTo(
                     mapOf(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
index 8e2eea1..a45ac9f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/data/repository/SceneContainerRepositoryTest.kt
@@ -140,23 +140,4 @@
                     ObservableTransitionState.Idle(kosmos.sceneContainerConfig.initialSceneKey)
                 )
         }
-
-    @Test
-    fun previousScene() =
-        testScope.runTest {
-            val underTest = kosmos.sceneContainerRepository
-            val currentScene by collectLastValue(underTest.currentScene)
-            val previousScene by collectLastValue(underTest.previousScene)
-
-            assertThat(previousScene).isNull()
-
-            val firstScene = currentScene
-            underTest.changeScene(Scenes.Shade)
-            assertThat(previousScene).isEqualTo(firstScene)
-            assertThat(currentScene).isEqualTo(Scenes.Shade)
-
-            underTest.changeScene(Scenes.QuickSettings)
-            assertThat(previousScene).isEqualTo(Scenes.Shade)
-            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
-        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
new file mode 100644
index 0000000..c75e297
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorTest.kt
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.scene.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.SceneKey
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
+import com.android.systemui.authentication.domain.interactor.AuthenticationResult
+import com.android.systemui.authentication.domain.interactor.authenticationInteractor
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SceneBackInteractorTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+    private val sceneInteractor = kosmos.sceneInteractor
+    private val sceneContainerStartable = kosmos.sceneContainerStartable
+    private val authenticationInteractor = kosmos.authenticationInteractor
+
+    private val underTest = kosmos.sceneBackInteractor
+
+    @Test
+    @EnableSceneContainer
+    fun navigateToQs_thenBouncer_thenBack_whileLocked() =
+        testScope.runTest {
+            sceneContainerStartable.start()
+
+            assertRoute(
+                RouteNode(Scenes.Lockscreen, null),
+                RouteNode(Scenes.Shade, Scenes.Lockscreen),
+                RouteNode(Scenes.QuickSettings, Scenes.Shade),
+                RouteNode(Scenes.Bouncer, Scenes.QuickSettings),
+                RouteNode(Scenes.QuickSettings, Scenes.Shade),
+                RouteNode(Scenes.Shade, Scenes.Lockscreen),
+                RouteNode(Scenes.Lockscreen, null),
+            )
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun navigateToQs_thenBouncer_thenUnlock() =
+        testScope.runTest {
+            sceneContainerStartable.start()
+
+            assertRoute(
+                RouteNode(Scenes.Lockscreen, null),
+                RouteNode(Scenes.Shade, Scenes.Lockscreen),
+                RouteNode(Scenes.QuickSettings, Scenes.Shade),
+                RouteNode(Scenes.Bouncer, Scenes.QuickSettings, unlockDevice = true),
+                RouteNode(Scenes.Gone, null),
+            )
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun navigateToQs_skippingShade_thenBouncer_thenBack_whileLocked() =
+        testScope.runTest {
+            sceneContainerStartable.start()
+
+            assertRoute(
+                RouteNode(Scenes.Lockscreen, null),
+                RouteNode(Scenes.QuickSettings, Scenes.Lockscreen),
+                RouteNode(Scenes.Bouncer, Scenes.QuickSettings),
+                RouteNode(Scenes.QuickSettings, Scenes.Lockscreen),
+                RouteNode(Scenes.Lockscreen, null),
+            )
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun navigateToBouncer_thenBack_whileLocked() =
+        testScope.runTest {
+            sceneContainerStartable.start()
+
+            assertRoute(
+                RouteNode(Scenes.Lockscreen, null),
+                RouteNode(Scenes.Bouncer, Scenes.Lockscreen),
+                RouteNode(Scenes.Lockscreen, null),
+            )
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun navigateToQs_skippingShade_thenBouncer_thenBack_thenShade_whileLocked() =
+        testScope.runTest {
+            sceneContainerStartable.start()
+
+            assertRoute(
+                RouteNode(Scenes.Lockscreen, null),
+                RouteNode(Scenes.QuickSettings, Scenes.Lockscreen),
+                RouteNode(Scenes.Bouncer, Scenes.QuickSettings),
+                RouteNode(Scenes.QuickSettings, Scenes.Lockscreen),
+                RouteNode(Scenes.Lockscreen, null),
+                RouteNode(Scenes.Shade, Scenes.Lockscreen),
+            )
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun navigateToQs_thenBack_whileUnlocked() =
+        testScope.runTest {
+            sceneContainerStartable.start()
+            unlockDevice()
+
+            assertRoute(
+                RouteNode(Scenes.Gone, null),
+                RouteNode(Scenes.Shade, Scenes.Gone),
+                RouteNode(Scenes.QuickSettings, Scenes.Shade),
+                RouteNode(Scenes.Shade, Scenes.Gone),
+                RouteNode(Scenes.Gone, null),
+            )
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun navigateToQs_skippingShade_thenBack_whileUnlocked() =
+        testScope.runTest {
+            sceneContainerStartable.start()
+            unlockDevice()
+
+            assertRoute(
+                RouteNode(Scenes.Gone, null),
+                RouteNode(Scenes.QuickSettings, Scenes.Gone),
+                RouteNode(Scenes.Gone, null),
+            )
+        }
+
+    @Test
+    @EnableSceneContainer
+    fun navigateToQs_skippingShade_thenBack_thenShade_whileUnlocked() =
+        testScope.runTest {
+            sceneContainerStartable.start()
+            unlockDevice()
+
+            assertRoute(
+                RouteNode(Scenes.Gone, null),
+                RouteNode(Scenes.QuickSettings, Scenes.Gone),
+                RouteNode(Scenes.Gone, null),
+                RouteNode(Scenes.Shade, Scenes.Gone),
+            )
+        }
+
+    private suspend fun TestScope.assertRoute(vararg route: RouteNode) {
+        val currentScene by collectLastValue(sceneInteractor.currentScene)
+        val backScene by collectLastValue(underTest.backScene)
+
+        route.forEachIndexed { index, node ->
+            sceneInteractor.changeScene(node.changeSceneTo, "")
+            assertWithMessage("node at index $index currentScene mismatch")
+                .that(currentScene)
+                .isEqualTo(node.changeSceneTo)
+            assertWithMessage("node at index $index backScene mismatch")
+                .that(backScene)
+                .isEqualTo(node.expectedBackScene)
+            if (node.unlockDevice) {
+                unlockDevice()
+            }
+        }
+    }
+
+    private suspend fun TestScope.unlockDevice() {
+        val currentScene by collectLastValue(sceneInteractor.currentScene)
+        runCurrent()
+        assertThat(authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
+            .isEqualTo(AuthenticationResult.SUCCEEDED)
+        assertThat(currentScene).isEqualTo(Scenes.Gone)
+    }
+
+    private data class RouteNode(
+        val changeSceneTo: SceneKey,
+        val expectedBackScene: SceneKey? = null,
+        val unlockDevice: Boolean = false,
+    )
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index 871ce6d..2fb8212 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -291,34 +291,4 @@
 
             assertThat(isVisible).isFalse()
         }
-
-    @Test
-    fun previousScene() =
-        testScope.runTest {
-            val currentScene by collectLastValue(underTest.currentScene)
-            val previousScene by collectLastValue(underTest.previousScene())
-            assertThat(previousScene).isNull()
-
-            val firstScene = currentScene
-            underTest.changeScene(toScene = Scenes.Shade, "reason")
-            assertThat(previousScene).isEqualTo(firstScene)
-
-            underTest.changeScene(toScene = Scenes.QuickSettings, "reason")
-            assertThat(previousScene).isEqualTo(Scenes.Shade)
-        }
-
-    @Test
-    fun previousScene_withIgnoredScene() =
-        testScope.runTest {
-            val currentScene by collectLastValue(underTest.currentScene)
-            val previousScene by collectLastValue(underTest.previousScene(ignored = Scenes.Shade))
-            assertThat(previousScene).isNull()
-
-            val firstScene = currentScene
-            underTest.changeScene(toScene = Scenes.Shade, "reason")
-            assertThat(previousScene).isEqualTo(firstScene)
-
-            underTest.changeScene(toScene = Scenes.QuickSettings, "reason")
-            assertThat(previousScene).isNull()
-        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 2586ad541..5779e37 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -392,6 +392,7 @@
                     Scenes.Gone,
                     Scenes.Lockscreen,
                     Scenes.Bouncer,
+                    Scenes.Gone,
                     Scenes.Shade,
                     Scenes.QuickSettings,
                 )
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index a8da116..e160cfc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -79,12 +79,12 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
 
-import java.util.List;
-import java.util.concurrent.Executor;
-
 import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
 import platform.test.runner.parameterized.Parameters;
 
+import java.util.List;
+import java.util.concurrent.Executor;
+
 @RunWith(ParameterizedAndroidJunit4.class)
 @RunWithLooper(setAsMainLooper = true)
 @SmallTest
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/SmartspaceViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/SmartspaceViewModelTest.kt
new file mode 100644
index 0000000..ffbbeb90
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/SmartspaceViewModelTest.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.smartspace
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
+import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.smartspace.ui.viewmodel.SmartspaceViewModel
+import com.android.systemui.smartspace.viewmodel.smartspaceViewModelFactory
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.flow.firstOrNull
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.withTimeoutOrNull
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SmartspaceViewModelTest : SysuiTestCase() {
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+
+    private val powerInteractor = kosmos.powerInteractor
+    private val smartspaceViewModelFactory = kosmos.smartspaceViewModelFactory
+
+    private lateinit var underTest: SmartspaceViewModel
+
+    @Test
+    fun dateVew_isAwakeTrue_true() =
+        testScope.runTest {
+            underTest = smartspaceViewModelFactory.create(SmartspaceViewModel.SURFACE_DATE_VIEW)
+
+            powerInteractor.setAwakeForTest()
+            val isAwake by collectLastValue(underTest.isAwake)
+
+            assertThat(isAwake).isTrue()
+        }
+
+    @Test
+    fun dateVew_isAwakeFalse_false() =
+        testScope.runTest {
+            underTest = smartspaceViewModelFactory.create(SmartspaceViewModel.SURFACE_DATE_VIEW)
+
+            powerInteractor.setAsleepForTest()
+            val isAwake by collectLastValue(underTest.isAwake)
+
+            assertThat(isAwake).isFalse()
+        }
+
+    @Test
+    fun dateVew_isAwakeMultipleTimes_correctResults() =
+        testScope.runTest {
+            underTest = smartspaceViewModelFactory.create(SmartspaceViewModel.SURFACE_DATE_VIEW)
+            val isAwake by collectLastValue(underTest.isAwake)
+
+            powerInteractor.setAsleepForTest()
+
+            assertThat(isAwake).isFalse()
+
+            powerInteractor.setAwakeForTest()
+
+            assertThat(isAwake).isTrue()
+
+            powerInteractor.setAsleepForTest()
+
+            assertThat(isAwake).isFalse()
+
+            powerInteractor.setAwakeForTest()
+
+            assertThat(isAwake).isTrue()
+        }
+
+    @Test
+    fun weatherView_isAwakeTrue_doesNotEmit() =
+        testScope.runTest {
+            underTest = smartspaceViewModelFactory.create(SmartspaceViewModel.SURFACE_WEATHER_VIEW)
+
+            powerInteractor.setAwakeForTest()
+            val isAwake = withTimeoutOrNull(100) { underTest.isAwake.firstOrNull() }
+
+            assertThat(isAwake).isNull()
+        }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 7fabe33..02993b8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar;
 
+import static android.app.Flags.FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS;
 import static android.app.Notification.VISIBILITY_PRIVATE;
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.VISIBILITY_NO_OVERRIDE;
@@ -24,7 +25,6 @@
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
-import static android.app.Flags.FLAG_KEYGUARD_PRIVATE_NOTIFICATIONS;
 import static android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES;
 import static android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE;
 import static android.os.UserHandle.USER_ALL;
@@ -73,7 +73,6 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FakeFeatureFlagsClassic;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.log.LogWtfHandlerRule;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.OverviewProxyService;
@@ -100,14 +99,14 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Executor;
 
-import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
-import platform.test.runner.parameterized.Parameters;
-
 @SmallTest
 @RunWith(ParameterizedAndroidJunit4.class)
 public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
index db8e14c1..0f66a93 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/BaseHeadsUpManagerTest.java
@@ -62,11 +62,11 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
-import java.util.List;
-
 import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
 import platform.test.runner.parameterized.Parameters;
 
+import java.util.List;
+
 @SmallTest
 @TestableLooper.RunWithLooper
 @RunWith(ParameterizedAndroidJunit4.class)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.java
index f66e75a..9feb914 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerPhoneTest.java
@@ -49,6 +49,8 @@
 import com.android.systemui.util.settings.GlobalSettings;
 import com.android.systemui.util.time.SystemClock;
 
+import kotlinx.coroutines.flow.StateFlowKt;
+
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Rule;
@@ -58,12 +60,11 @@
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
-import java.util.List;
-
-import kotlinx.coroutines.flow.StateFlowKt;
 import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
 import platform.test.runner.parameterized.Parameters;
 
+import java.util.List;
+
 @SmallTest
 @RunWith(ParameterizedAndroidJunit4.class)
 @TestableLooper.RunWithLooper
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTestUtil.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTestUtil.java
index bda8619..306d6efd 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTestUtil.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/HeadsUpManagerTestUtil.java
@@ -16,13 +16,12 @@
 
 package com.android.systemui.statusbar.policy;
 import android.app.ActivityManager;
+import android.app.Notification;
 import android.app.PendingIntent;
+import android.content.Context;
 import android.content.Intent;
 import android.os.UserHandle;
-
-import android.content.Context;
 import android.service.notification.StatusBarNotification;
-import android.app.Notification;
 
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/EventsTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/EventsTest.java
similarity index 96%
rename from packages/SystemUI/tests/src/com/android/systemui/volume/EventsTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/volume/EventsTest.java
index c69f5c8..87e1f86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/EventsTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/EventsTest.java
@@ -34,12 +34,15 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
 
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Queue;
 
+import platform.test.runner.parameterized.Parameter;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
 /**
  * Parameterized unit test for Events.logEvent.
  *
@@ -51,7 +54,7 @@
  * either SysuiTestCase or SysUiBaseFragmentTest.
  *
  */
-@RunWith(Parameterized.class)
+@RunWith(ParameterizedAndroidJunit4.class)
 @SmallTest
 public class EventsTest extends SysuiTestCase {
     private FakeMetricsLogger mLegacyLogger;
@@ -66,23 +69,23 @@
     }
 
     // Parameters for calling writeEvent with arbitrary args.
-    @Parameterized.Parameter
+    @Parameter
     public int mTag;
 
-    @Parameterized.Parameter(1)
+    @Parameter(1)
     public Object[] mArgs;
 
     // Expect returned string exactly matches.
-    @Parameterized.Parameter(2)
+    @Parameter(2)
     public String mExpectedMessage;
 
     // Expect these MetricsLogger calls.
 
-    @Parameterized.Parameter(3)
+    @Parameter(3)
     public int[] mExpectedMetrics;
 
     // Expect this UiEvent (use null if there isn't one).
-    @Parameterized.Parameter(4)
+    @Parameter(4)
     public UiEventLogger.UiEventEnum mUiEvent;
 
     @Test
@@ -108,7 +111,10 @@
         }
     }
 
-    @Parameterized.Parameters(name = "{index}: {2}")
+    /**
+     * Collection of parameters for the test.
+     */
+    @Parameters(name = "{index}: {2}")
     public static Collection<Object[]> data() {
         return Arrays.asList(new Object[][]{
                 {Events.EVENT_SETTINGS_CLICK, null,
@@ -217,4 +223,3 @@
         });
     }
 }
-
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/UtilTest.java
similarity index 95%
rename from packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/volume/UtilTest.java
index 483dc0c..d6c63af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/UtilTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/UtilTest.java
@@ -19,13 +19,16 @@
 
 import android.media.MediaMetadata;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
 
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 @SmallTest
+@RunWith(AndroidJUnit4.class)
 public class UtilTest extends SysuiTestCase {
 
     @Test
diff --git a/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java b/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java
index 79a0c35..4a0626c 100644
--- a/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java
+++ b/packages/SystemUI/plugin/ExamplePlugin/src/com/android/systemui/plugin/testoverlayplugin/SampleOverlayPlugin.java
@@ -20,9 +20,9 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-
 import android.view.ViewTreeObserver.InternalInsetsInfo;
 import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
+
 import com.android.systemui.plugins.OverlayPlugin;
 import com.android.systemui.plugins.annotations.Requires;
 
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/IntentButtonProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/IntentButtonProvider.java
index 97dbafd..63bb24f 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/IntentButtonProvider.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/IntentButtonProvider.java
@@ -14,11 +14,11 @@
 
 package com.android.systemui.plugins;
 
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 
+import com.android.systemui.plugins.annotations.ProvidesInterface;
+
 /**
  * An Intent Button represents a triggerable element in SysUI that consists of an
  * Icon and an intent to trigger when it is activated (clicked, swiped, etc.).
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java
index f79cd86..4113c04 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NotificationPersonExtractorPlugin.java
@@ -17,7 +17,6 @@
 package com.android.systemui.plugins;
 
 import android.annotation.Nullable;
-import android.app.PendingIntent;
 import android.graphics.drawable.Drawable;
 import android.service.notification.StatusBarNotification;
 
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginUtils.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginUtils.java
index af49d43..acb6f11 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginUtils.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/PluginUtils.java
@@ -15,7 +15,6 @@
 package com.android.systemui.plugins;
 
 import android.content.Context;
-import android.view.LayoutInflater;
 import android.view.View;
 
 public class PluginUtils {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
index 02085b9..4c5ca2fd 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/StatusBarStateController.java
@@ -19,7 +19,6 @@
 import com.android.systemui.plugins.annotations.DependsOn;
 import com.android.systemui.plugins.annotations.ProvidesInterface;
 
-
 /**
  * Sends updates to {@link StateListener}s about changes to the status bar state and dozing state
  */
diff --git a/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/Plugin.java b/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/Plugin.java
index bb93367..8ff6c11 100644
--- a/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/Plugin.java
+++ b/packages/SystemUI/plugin_core/src/com/android/systemui/plugins/Plugin.java
@@ -13,10 +13,10 @@
  */
 package com.android.systemui.plugins;
 
-import com.android.systemui.plugins.annotations.Requires;
-
 import android.content.Context;
 
+import com.android.systemui.plugins.annotations.Requires;
+
 /**
  * Plugins are separate APKs that
  * are expected to implement interfaces provided by SystemUI.  Their
diff --git a/packages/SystemUI/res-product/values-or/strings.xml b/packages/SystemUI/res-product/values-or/strings.xml
index 5d9345b..a89dd7b 100644
--- a/packages/SystemUI/res-product/values-or/strings.xml
+++ b/packages/SystemUI/res-product/values-or/strings.xml
@@ -30,9 +30,9 @@
     <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ଏହି ଫୋନ୍‌କୁ ରିସେଟ୍ କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"ଆପଣ ଟାବ୍‌ଲେଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଟାବ୍‌ଲେଟ୍‌ଟି ରିସେଟ୍ କରିଦିଆଯିବ, ଫଳରେ ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଫୋନ୍‌ଟି ରିସେଟ୍ କରିଦିଆଯିବ, ଫଳରେ ଏହାର ସମସ୍ତ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ଆପଣ ଟାବ୍‌ଲେଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ଏହି ଉପଯୋଗକର୍ତ୍ତା ପ୍ରୋଫାଇଲ୍‌କୁ କାଢ଼ିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ଏହି ଉପଯୋଗକର୍ତ୍ତା ପ୍ରୋଫାଇଲ୍‌କୁ କାଢ଼ିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ଆପଣ ଟାବ୍‌ଲେଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ବାହାର କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"ଆପଣ ଟାବଲେଟକୁ ଅନଲକ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g> ଭୁଲ ପ୍ରୟାସ ପରେ, ଏହି ୟୁଜର ପ୍ରୋଫାଇଲ୍କୁ କାଢ଼ି ଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ୟୁଜର ଡାଟା ଡିଲିଟ ହୋଇଯିବ।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"ଆପଣ ଫୋନକୁ ଅନଲକ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g> ଭୁଲ ପ୍ରୟାସ ପରେ, ଏହି ୟୁଜର ପ୍ରୋଫାଇଲକୁ କାଢ଼ି ଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ୟୁଜର ଡାଟା ଡିଲିଟ ହୋଇଯିବ।"</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"ଆପଣ ଟାବଲେଟକୁ ଅନଲକ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ୟୁଜରଙ୍କୁ ବାହାର କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ ହୋଇଯିବ।"</string>
     <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER">%d</xliff:g>ଥର ଭୁଲ୍ ପ୍ରୟାସ କରିଛନ୍ତି। ଏହି ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ବାହାର କରିଦିଆଯିବ, ଯାହାଦ୍ୱାରା ସମସ୍ତ ଉପଯୋଗକର୍ତ୍ତା ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
     <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"ଆପଣ ଟାବ୍‌ଲେଟ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ୱାର୍କ ପ୍ରୋଫାଇଲ୍‌କୁ ବାହାର କରିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ପ୍ରୋଫାଇଲ୍ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
     <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"ଆପଣ ଫୋନ୍‌କୁ ଅନ୍‌ଲକ୍ କରିବାକୁ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ପ୍ରୟାସ କରିଛନ୍ତି। ଆଉ <xliff:g id="NUMBER_1">%2$d</xliff:g>ଟି ଭୁଲ୍ ପ୍ରୟାସ ପରେ, ୱାର୍କ ପ୍ରୋଫାଇଲ୍‌କୁ ବାହାର କରିଦିଆଯିବ, ଯାହା ଫଳରେ ସମସ୍ତ ପ୍ରୋଫାଇଲ୍ ଡାଟା ଡିଲିଟ୍ ହେବ।"</string>
diff --git a/packages/SystemUI/res/drawable/face_dialog_dark_to_checkmark.xml b/packages/SystemUI/res/drawable/face_dialog_dark_to_checkmark.xml
index fe19516..fb30249 100644
--- a/packages/SystemUI/res/drawable/face_dialog_dark_to_checkmark.xml
+++ b/packages/SystemUI/res/drawable/face_dialog_dark_to_checkmark.xml
@@ -40,7 +40,7 @@
                             <path
                                 android:name="_R_G_L_0_G_D_0_P_0"
                                 android:fillAlpha="0"
-                                android:fillColor="@color/biometric_dialog_accent"
+                                android:fillColor="@color/biometric_dialog_face_checkmark"
                                 android:fillType="nonZero"
                                 android:pathData=" M-116 -16.5 C-116,-16.5 -31.25,68.5 -31.25,68.5 C-31.25,68.5 108.75,-71.5 108.75,-71.5 "
                                 android:trimPathStart="0"
@@ -58,7 +58,7 @@
                                 android:pathData=" M-116 -16.5 C-116,-16.5 -31.25,68.5 -31.25,68.5 C-31.25,68.5 108.75,-71.5 108.75,-71.5 "
                                 android:strokeWidth="20"
                                 android:strokeAlpha="1"
-                                android:strokeColor="@color/biometric_dialog_accent"
+                                android:strokeColor="@color/biometric_dialog_face_checkmark"
                                 android:trimPathStart="0"
                                 android:trimPathEnd="0"
                                 android:trimPathOffset="0" />
@@ -68,7 +68,7 @@
                             android:pathData=" M30 6.2 C16.9,6.2 6.3,16.8 6.3,30 C6.3,43.2 16.9,53.8 30,53.8 C43.1,53.8 53.8,43.2 53.8,30 C53.8,16.8 43.1,6.2 30,6.2c "
                             android:strokeWidth="2.5"
                             android:strokeAlpha="1"
-                            android:strokeColor="@color/biometric_dialog_accent"
+                            android:strokeColor="@color/biometric_dialog_face_checkmark"
                             android:trimPathStart="0"
                             android:trimPathEnd="1"
                             android:trimPathOffset="0" />
@@ -387,7 +387,7 @@
                     android:propertyName="strokeColor"
                     android:startOffset="0"
                     android:valueFrom="@color/biometric_dialog_accent"
-                    android:valueTo="@color/biometric_dialog_accent"
+                    android:valueTo="@color/biometric_dialog_face_checkmark"
                     android:valueType="colorType">
                     <aapt:attr name="android:interpolator">
                         <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
@@ -398,7 +398,7 @@
                     android:propertyName="strokeColor"
                     android:startOffset="67"
                     android:valueFrom="@color/biometric_dialog_accent"
-                    android:valueTo="@color/biometric_dialog_accent"
+                    android:valueTo="@color/biometric_dialog_face_checkmark"
                     android:valueType="colorType">
                     <aapt:attr name="android:interpolator">
                         <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
diff --git a/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml
index 8e3cf4d..91ca69e 100644
--- a/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml
+++ b/packages/SystemUI/res/layout/biometric_prompt_constraint_layout.xml
@@ -47,7 +47,7 @@
         android:layout_height="wrap_content"
         android:fillViewport="true"
         android:fadeScrollbars="false"
-        android:paddingBottom="36dp"
+        android:paddingBottom="24dp"
         android:paddingHorizontal="24dp"
         android:paddingTop="24dp"
         app:layout_constrainedHeight="true"
diff --git a/packages/SystemUI/res/layout/screenshot_shelf.xml b/packages/SystemUI/res/layout/screenshot_shelf.xml
index 26d3f43..79b82bf 100644
--- a/packages/SystemUI/res/layout/screenshot_shelf.xml
+++ b/packages/SystemUI/res/layout/screenshot_shelf.xml
@@ -59,7 +59,7 @@
         android:layout_marginTop="@dimen/overlay_border_width_neg"
         android:layout_marginEnd="@dimen/overlay_border_width_neg"
         android:layout_marginBottom="@dimen/screenshot_shelf_vertical_margin"
-        android:elevation="8dp"
+        android:elevation="4dp"
         android:background="@drawable/overlay_border"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="@id/screenshot_preview"
@@ -72,7 +72,7 @@
         android:layout_marginStart="@dimen/overlay_border_width"
         android:layout_marginBottom="@dimen/overlay_border_width"
         android:layout_gravity="center"
-        android:elevation="8dp"
+        android:elevation="4dp"
         android:contentDescription="@string/screenshot_edit_description"
         android:scaleType="fitEnd"
         android:background="@drawable/overlay_preview_background"
@@ -85,14 +85,14 @@
         android:layout_width="56dp"
         android:layout_height="56dp"
         android:visibility="gone"
-        android:elevation="9dp"
+        android:elevation="5dp"
         app:layout_constraintBottom_toBottomOf="@id/screenshot_preview_border"
         app:layout_constraintEnd_toEndOf="@id/screenshot_preview_border"/>
     <FrameLayout
         android:id="@+id/screenshot_dismiss_button"
         android:layout_width="@dimen/overlay_dismiss_button_tappable_size"
         android:layout_height="@dimen/overlay_dismiss_button_tappable_size"
-        android:elevation="11dp"
+        android:elevation="7dp"
         android:visibility="gone"
         app:layout_constraintStart_toEndOf="@id/screenshot_preview"
         app:layout_constraintEnd_toEndOf="@id/screenshot_preview"
diff --git a/packages/SystemUI/res/raw/keep.xml b/packages/SystemUI/res/raw/keep.xml
new file mode 100644
index 0000000..645e3c5
--- /dev/null
+++ b/packages/SystemUI/res/raw/keep.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright (C) 2024 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources xmlns:tools="http://schemas.android.com/tools"
+    tools:keep="@drawable/homecontrols_sq" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 63c6132..799b88a 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -458,8 +458,7 @@
     <string name="work_mode_off_title" msgid="5794818421357835873">"Hervat werkapps?"</string>
     <string name="work_mode_turn_on" msgid="907813741770247267">"Hervat"</string>
     <string name="accessibility_action_label_close_communal_hub" msgid="6790396569621032333">"Maak legstukke op sluitskerm toe"</string>
-    <!-- no translation found for accessibility_action_label_edit_widgets (3821868581348322346) -->
-    <skip />
+    <string name="accessibility_action_label_edit_widgets" msgid="3821868581348322346">"Pasmaak legstukke"</string>
     <string name="accessibility_content_description_for_communal_hub" msgid="1670220840599380118">"Legstukke op sluitskerm"</string>
     <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Wissel gebruiker"</string>
     <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"aftrekkieslys"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliet, swak verbinding"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliet, goeie toestand"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding is beskikbaar"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Pret vir party mense, maar nie vir almal nie"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Stelsel-UI-ontvanger gee jou ekstra maniere om die Android-gebruikerkoppelvlak in te stel en te pasmaak. Hierdie eksperimentele kenmerke kan in toekomstige uitreikings verander, breek of verdwyn. Gaan versigtig voort."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 1c80547..6db4e02 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ሳተላይት፣ ደካማ ግንኙነት"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ሳተላይት፣ ጥሩ ግንኙነት"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ሳተላይት፣ ግንኙነት አለ"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"የስራ መገለጫ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ለአንዳንዶች አስደሳች ቢሆንም ለሁሉም አይደለም"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"የስርዓት በይነገጽ መቃኛ የAndroid ተጠቃሚ በይነገጹን የሚነካኩበት እና የሚያበጁበት ተጨማሪ መንገዶች ይሰጠዎታል። እነዚህ የሙከራ ባህሪዎች ወደፊት በሚኖሩ ልቀቶች ላይ ሊለወጡ፣ ሊሰበሩ ወይም ሊጠፉ ይችላሉ። ከጥንቃቄ ጋር ወደፊት ይቀጥሉ።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index c92a32b..7f89ab49 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"قمر صناعي، الاتصال ضعيف"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"قمر صناعي، الاتصال جيد"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"قمر صناعي، الاتصال متوفّر"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ملف العمل"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"متعة للبعض وليس للجميع"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‏توفر لك أداة ضبط واجهة مستخدم النظام طرقًا إضافية لتعديل واجهة مستخدم Android وتخصيصها. ويمكن أن تطرأ تغييرات على هذه الميزات التجريبية أو يمكن أن تتعطل هذه الميزات أو تختفي في الإصدارات المستقبلية. عليك متابعة الاستخدام مع توخي الحذر."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index f1291a0..c2dc3b0 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"উপগ্ৰহ, বেয়া সংযোগ"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"উপগ্ৰহ, ভাল সংযোগ"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"উপগ্ৰহ, সংযোগ উপলব্ধ"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"কিছুমানৰ বাবে আমোদজনক হয় কিন্তু সকলোৰে বাবে নহয়"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tunerএ আপোনাক Android ব্যৱহাৰকাৰী ইণ্টাৰফেইচ সলনি কৰিবলৈ আৰু নিজৰ উপযোগিতা অনুসৰি ব্যৱহাৰ কৰিবলৈ অতিৰিক্ত সুবিধা প্ৰদান কৰে। এই পৰীক্ষামূলক সুবিধাসমূহ সলনি হ\'ব পাৰে, সেইবোৰে কাম নকৰিব পাৰে বা আগন্তুক সংস্কৰণসমূহত সেইবোৰ অন্তৰ্ভুক্ত কৰা নহ’ব পাৰে। সাৱধানেৰে আগবাঢ়ক।"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index b12d822..853a020 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Peyk, bağlantı zəifdir"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Peyk, bağlantı yaxşıdır"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Peyk, bağlantı var"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Hamı üçün deyil, bəziləri üçün əyləncəli"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android istifadəçi interfeysini dəyişdirmək və fərdiləşdirmək üçün Sizə ekstra yollar təklif edir."</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 221d16c..80cc48f 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Slušni aparati"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Upari novi uređaj"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknite da biste uparili nov uređaj"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ažuriranje zadatih podešavanja nije uspelo"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Želite da odblokirate mikrofon uređaja?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Želite da odblokirate kameru uređaja?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Želite da odblokirate kameru i mikrofon uređaja?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, veza je loša"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, veza je dobra"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Tjuner za korisnički interfejs sistema vam pruža dodatne načine za podešavanje i prilagođavanje Android korisničkog interfejsa. Ove eksperimentalne funkcije mogu da se promene, otkažu ili nestanu u budućim izdanjima. Budite oprezni."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index d1c4a98..d64ffe8 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Спадарожнікавая сувязь, дрэннае падключэнне"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спадарожнікавая сувязь, добрае падключэнне"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спадарожнікавая сувязь, падключэнне даступнае"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Працоўны профіль"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Цікава для некаторых, але не для ўсіх"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Наладка сістэмнага інтэрфейсу карыстальніка дае вам дадатковыя спосабы наладжвання і дапасоўвання карыстальніцкага інтэрфейсу Android. Гэтыя эксперыментальныя функцыі могуць змяніцца, перастаць працаваць або знікнуць у будучых версіях. Карыстайцеся з асцярожнасцю."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 62d3fed..b3321f5 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Сателит, лоша връзка"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Сателит, добра връзка"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, налице е връзка"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Потребителски профил в Work"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Забавно – но не за всички"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Тунерът на системния потребителски интерфейс ви предоставя допълнителни възможности за прецизиране и персонализиране на практическата работа с Android. Тези експериментални функции може да се променят, повредят или да изчезнат в бъдещите версии. Действайте внимателно."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 81e3fc4..5c3d96b 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"স্যাটেলাইট, খারাপ কানেকশন"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"স্যাটেলাইট, ভালো কানেকশন"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"স্যাটেলাইট, কানেকশন উপলভ্য আছে"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"কাজের প্রোফাইল"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"কিছু ব্যক্তির জন্য মজাদার কিন্তু সকলের জন্য নয়"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"এই পরীক্ষামূলক বৈশিষ্ট্যগুলি ভবিষ্যতের সংস্করণগুলির মধ্যে পরিবর্তিত, বিভাজিত এবং অদৃশ্য হয়ে যেতে পারে৷ সাবধানতার সাথে এগিয়ে যান৷ সিস্টেম UI টিউনার আপনাকে Android ব্যবহারকারী ইন্টারফেসের সূক্ষ্ম সমন্বয় এবং কাস্টমাইজ করার অতিরিক্ত উপায়গুলি প্রদান করে৷"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 7d66851..f3ffe26 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -235,8 +235,8 @@
     <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 lokacija za obavještenja."</string>
-    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Zaključavanje ekrana"</string>
-    <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključan ekran radnog profila"</string>
+    <string name="accessibility_desc_lock_screen" msgid="409034672704273634">"Zaključani ekran"</string>
+    <string name="accessibility_desc_work_lock" msgid="4355620395354680575">"Zaključani ekran radnog profila"</string>
     <string name="accessibility_desc_close" msgid="8293708213442107755">"Zatvori"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"potpuna tišina"</string>
     <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"samo alarmi"</string>
@@ -643,7 +643,7 @@
     <string name="wallet_secondary_label_updating" msgid="5726130686114928551">"Ažuriranje"</string>
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da koristite"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema prilikom preuzimanja vaših kartica. Pokušajte ponovo kasnije"</string>
-    <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključavanja ekrana"</string>
+    <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključanog ekrana"</string>
     <string name="qr_code_scanner_title" msgid="1938155688725760702">"Skener QR koda"</string>
     <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Ažuriranje"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"Radni profil"</string>
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slaba veza"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra veza"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Radni profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Podešavač za korisnički interfejs sistema vam omogućava dodatne načine da podesite i prilagodite Androidov interfejs. Ove eksperimentalne funkcije se u budućim verzijama mogu mijenjati, kvariti ili nestati. Budite oprezni."</string>
@@ -775,7 +779,7 @@
     <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otvaranje liste aplikacija"</string>
     <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvaranje postavki"</string>
     <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvaranje Asistenta"</string>
-    <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključavanje ekrana"</string>
+    <string name="group_system_lock_screen" msgid="7391191300363416543">"Zaključani ekran"</string>
     <string name="group_system_quick_memo" msgid="3764560265935722903">"Pisanje bilješke"</string>
     <string name="keyboard_shortcut_group_system_multitasking" msgid="6967816258924795558">"Multitasking"</string>
     <string name="system_multitasking_rhs" msgid="8714224917276297810">"Korištenje podijeljenog ekrana s trenutnom aplikacijom na desnoj strani"</string>
@@ -1275,8 +1279,8 @@
     <string name="call_from_work_profile_action" msgid="2937701298133010724">"Pređite na radni profil"</string>
     <string name="install_dialer_on_work_profile_action" msgid="2014659711597862506">"Instalirajte poslovnu aplikaciju za telefon"</string>
     <string name="call_from_work_profile_close" msgid="5830072964434474143">"Otkaži"</string>
-    <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagodi zaključavanje ekrana"</string>
-    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da prilagodite zaključavanje ekrana"</string>
+    <string name="lock_screen_settings" msgid="6152703934761402399">"Prilagodi zaključani ekran"</string>
+    <string name="keyguard_unlock_to_customize_ls" msgid="2068542308086253819">"Otključajte da prilagodite zaključani ekran"</string>
     <string name="wifi_unavailable_dream_overlay_content_description" msgid="2024166212194640100">"WiFi mreža nije dostupna"</string>
     <string name="camera_blocked_dream_overlay_content_description" msgid="4074759493559418130">"Kamera je blokirana"</string>
     <string name="camera_and_microphone_blocked_dream_overlay_content_description" msgid="7891078093416249764">"Kamera i mikrofon su blokirani"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 87af353..341dca5 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Audiòfons"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Vincula un dispositiu nou"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Fes clic per vincular un dispositiu nou"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"No s\'ha pogut actualitzar el valor predefinit"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Vols desbloquejar el micròfon del dispositiu?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Vols desbloquejar la càmera del dispositiu?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Vols desbloquejar la càmera i el micròfon del dispositiu?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satèl·lit, connexió deficient"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satèl·lit, bona connexió"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satèl·lit, connexió disponible"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de treball"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversió per a uns quants, però no per a tothom"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"El Personalitzador d\'interfície d\'usuari presenta opcions addicionals per canviar i personalitzar la interfície d\'usuari d\'Android. És possible que aquestes funcions experimentals canviïn, deixin de funcionar o desapareguin en versions futures. Continua amb precaució."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 102768f..ad5a76ac 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, špatné připojení"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobré připojení"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, připojení je k dispozici"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovní profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zábava, která není pro každého"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Nástroj na ladění uživatelského rozhraní systému vám nabízí další způsoby, jak si vyladit a přizpůsobit uživatelské rozhraní Android. Tyto experimentální funkce mohou v dalších verzích chybět, nefungovat nebo být změněny. Postupujte proto prosím opatrně."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index d3138ab..f65364f 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellit – dårlig forbindelse"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit – god forbindelse"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit – forbindelsen er tilgængelig"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbejdsprofil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Sjovt for nogle, men ikke for alle"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner giver dig flere muligheder for at justere og tilpasse Android-brugerfladen. Disse eksperimentelle funktioner kan ændres, gå i stykker eller forsvinde i fremtidige udgivelser. Vær forsigtig, hvis du fortsætter."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 03d04a6..3161b86 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellit, Verbindung schlecht"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit, Verbindung gut"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, Verbindung verfügbar"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbeitsprofil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Für einige ein Vergnügen, aber nicht für alle"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Mit System UI Tuner erhältst du zusätzliche Möglichkeiten, die Android-Benutzeroberfläche anzupassen. Achtung: Diese Testfunktionen können sich ändern, abstürzen oder in zukünftigen Versionen verschwinden."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 89092ad..33dc496 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Δορυφορική, κακή σύνδεση"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Δορυφορική, καλή σύνδεση"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Δορυφορική, διαθέσιμη σύνδεση"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Προφίλ εργασίας"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Διασκέδαση για ορισμένους, αλλά όχι για όλους"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Το System UI Tuner σάς προσφέρει επιπλέον τρόπους για να τροποποιήσετε και να προσαρμόσετε τη διεπαφή χρήστη Android. Αυτές οι πειραματικές λειτουργίες ενδέχεται να τροποποιηθούν, να παρουσιάσουν σφάλματα ή να καταργηθούν σε μελλοντικές εκδόσεις. Συνεχίστε με προσοχή."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 459de64..e0786ce 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 4879850..8b71d4b 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -654,6 +654,8 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
+    <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Connected to satellite"</string>
+    <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Not connected to satellite"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customize the Android user interface. These experimental features may change, break, or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 459de64..e0786ce 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 459de64..e0786ce 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, poor connection"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index a2340bd..f32b774 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -654,6 +654,8 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‎‎Satellite, poor connection‎‏‎‎‏‎"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‏‎‎‎‎‏‎‎‏‎‎‏‎‎‏‏‎‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎Satellite, good connection‎‏‎‎‏‎"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‏‏‏‎‏‎Satellite, connection available‎‏‎‎‏‎"</string>
+    <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎Connected to satellite‎‏‎‎‏‎"</string>
+    <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎Not connected to satellite‎‏‎‎‏‎"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‎‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎Work profile‎‏‎‎‏‎"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‏‎‎‏‏‏‏‏‏‎‎‎‎‏‎‏‏‎‎‏‎‏‎‎‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎Fun for some but not for all‎‏‎‎‏‎"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎System UI Tuner gives you extra ways to tweak and customize the Android user interface. These experimental features may change, break, or disappear in future releases. Proceed with caution.‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 202bd93..3b6f249 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, conexión inestable"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, buena conexión"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversión para algunos, pero no para todos"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"El sintonizador de IU del sistema te brinda más formas para editar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, dejar de funcionar o no incluirse en futuras versiones. Procede con precaución."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 88fab2d..42d403d 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, mala conexión"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, buena conexión"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversión solo para algunos"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"El configurador de UI del sistema te ofrece otras formas de modificar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, fallar o desaparecer en futuras versiones. Te recomendamos que tengas cuidado."</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 1b4cea7..f3c75a4 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Kuuldeseadmed"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Uue seadme sidumine"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Uue seadme sidumiseks klõpsake"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Eelseadistust ei saanud värskendada"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Kas tühistada seadme mikrofoni blokeerimine?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Kas tühistada seadme kaamera blokeerimine?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Kas tühistada seadme kaamera ja mikrofoni blokeerimine?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliit, kehv ühendus"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliit, hea ühendus"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliit, ühendus on saadaval"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Tööprofiil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Kõik ei pruugi sellest rõõmu tunda"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Süsteemi kasutajaliidese tuuner pakub täiendavaid võimalusi Androidi kasutajaliidese muutmiseks ja kohandamiseks. Need katselised funktsioonid võivad muutuda, rikki minna või tulevastest versioonidest kaduda. Olge jätkamisel ettevaatlik."</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index b69ef30..da885b7 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelitea, konexio ahula"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelitea, konexio ona"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelitea, konexioa erabilgarri"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Laneko profila"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Dibertsioa batzuentzat, baina ez guztientzat"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Sistemaren erabiltzaile-interfazearen konfiguratzaileak Android erabiltzaile-interfazea moldatzeko eta pertsonalizatzeko modu gehiago eskaintzen dizkizu. Baliteke eginbide esperimental horiek hurrengo kaleratzeetan aldatuta, etenda edo desagertuta egotea. Kontuz erabili."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 94fb12f..b63ec78 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ماهواره، اتصال ضعیف است"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ماهواره، اتصال خوب است"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ماهواره، اتصال دردسترس است"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"نمایه کاری"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"برای بعضی افراد سرگرم‌کننده است اما نه برای همه"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‏«تنظیم‌کننده واسط کاربری سیستم» روش‌های بیشتری برای تنظیم دقیق و سفارشی کردن واسط کاربری Android در اختیار شما قرار می‌دهد. ممکن است این ویژگی‌های آزمایشی تغییر کنند، خراب شوند یا در نسخه‌های آینده جود نداشته باشند. با احتیاط ادامه دهید."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index a7754b0..21df7c7 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Kuulolaitteet"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Muodosta uusi laitepari"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Muodosta uusi laitepari klikkaamalla"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Esiasetusta ei voitu muuttaa"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Kumotaanko laitteen mikrofonin esto?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Kumotaanko laitteen kameran esto?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Kumotaanko laitteen kameran ja mikrofonin esto?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliitti, huono yhteys"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliitti, hyvä yhteys"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliitti, yhteys saatavilla"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Työprofiili"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Ei sovellu kaikkien käyttöön"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner antaa lisämahdollisuuksia Android-käyttöliittymän muokkaamiseen. Nämä kokeelliset ominaisuudet voivat muuttua, lakata toimimasta tai kadota milloin tahansa. Jatka omalla vastuullasi."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 5bacaaa..850f977 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Connexion satellite faible"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Bonne connexion satellite"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite accessible"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur d\'Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index a4a039f1..0df8988 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Appareils auditifs"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Associer un nouvel appareil"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Cliquer pour associer un nouvel appareil"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Impossible de mettre à jour les préréglages"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Débloquer le micro de l\'appareil ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Débloquer la caméra de l\'appareil ?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Débloquer l\'appareil photo et le micro de l\'appareil ?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Mauvaise connexion satellite"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Bonne connexion satellite"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite disponible"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index e2b1e53..10e8601 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, mala conexión"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, boa conexión"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión dispoñible"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de traballo"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversión só para algúns"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"O configurador da IU do sistema ofréceche formas adicionais de modificar e personalizar a interface de usuario de Android. Estas funcións experimentais poden cambiar, interromperse ou desaparecer en futuras versións. Continúa con precaución."</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 2883cc5..ebfe6f7 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"સૅટલાઇટ, નબળું કનેક્શન"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"સૅટલાઇટ, સારું કનેક્શન"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"સૅટલાઇટ, કનેક્શન ઉપલબ્ધ છે"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ઑફિસની પ્રોફાઇલ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"કેટલાક માટે મજા પરંતુ બધા માટે નહીં"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"સિસ્ટમ UI ટ્યૂનર તમને Android વપરાશકર્તા ઇન્ટરફેસને ટ્વીક અને કસ્ટમાઇઝ કરવાની વધારાની રીતો આપે છે. ભાવિ રીલિઝેસમાં આ પ્રાયોગિક સુવિધાઓ બદલાઈ, ભંગ અથવા અદૃશ્ય થઈ શકે છે. સાવધાની સાથે આગળ વધો."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index f30957d..ea50302 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"कान की मशीनें"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"नया डिवाइस जोड़ें"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"नया डिवाइस जोड़ने के लिए क्लिक करें"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"प्रीसेट अपडेट नहीं किया जा सका"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"क्या आपको डिवाइस का माइक्रोफ़ोन अनब्लॉक करना है?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"क्या आपको डिवाइस का कैमरा अनब्लॉक करना है?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"क्या आप डिवाइस का कैमरा और माइक्रोफ़ोन अनब्लॉक करना चाहते हैं?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"सैटलाइट कनेक्शन खराब है"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"सैटलाइट कनेक्शन अच्छा है"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सैटलाइट कनेक्शन उपलब्ध है"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"वर्क प्रोफ़ाइल"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"कुछ के लिए मज़ेदार लेकिन सबके लिए नहीं"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर, आपको Android यूज़र इंटरफ़ेस में सुधार लाने और उसे अपनी पसंद के हिसाब से बदलने के कुछ और तरीके देता है. प्रयोग के तौर पर इस्तेमाल हो रहीं ये सुविधाएं आगे चल कर रिलीज़ की जा सकती हैं, रोकी जा सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index bada67e..b1849c5 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slaba veza"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra veza"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Ugađanje korisničkog sučelja sustava pruža vam dodatne načine za prilagodbu korisničkog sučelja Androida. Te se eksperimentalne značajke mogu promijeniti, prekinuti ili nestati u budućim izdanjima. Nastavite uz oprez."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index d216fa4..ddae886 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Hallókészülékek"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Új eszköz párosítása"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kattintson új eszköz párosításához"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nem sikerült frissíteni a beállításkészletet"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Feloldja az eszköz mikrofonjának letiltását?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Feloldja az eszköz kamerájának letiltását?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Feloldja az eszköz kamerájának és mikrofonjának letiltását?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Műhold, gyenge kapcsolat"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Műhold, jó kapcsolat"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Műhold, van rendelkezésre álló kapcsolat"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Munkaprofil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Egyeseknek tetszik, másoknak nem"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"A Kezelőfelület-hangoló az Android felhasználói felületének szerkesztéséhez és testreszabásához nyújt további megoldásokat. Ezek a kísérleti funkciók változhatnak vagy megsérülhetnek a későbbi kiadásokban, illetve eltűnhetnek azokból. Körültekintően járjon el."</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 034ac1a..717732d 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Արբանյակային թույլ կապ"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Արբանյակային լավ կապ"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Հասանելի է արբանյակային կապ"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Աշխատանքային պրոֆիլ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Զվարճանք մեկ՝ որոշակի մարդու համար"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Համակարգի ՕՄ-ի կարգավորիչը հնարավորություն է տալիս հարմարեցնել Android-ի օգտատիրոջ միջերեսը: Այս փորձնական գործառույթները կարող են հետագա թողարկումների մեջ փոփոխվել, խափանվել կամ ընդհանրապես չհայտնվել: Եթե շարունակում եք, զգուշացեք:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index d428ef8..d5e353a 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, koneksi buruk"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, koneksi baik"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, koneksi tersedia"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Tidak semua orang menganggapnya baik"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Penyetel Antarmuka Pengguna Sistem memberikan cara tambahan untuk mengubah dan menyesuaikan antarmuka pengguna Android. Fitur eksperimental ini dapat berubah, rusak, atau menghilang dalam rilis di masa mendatang. Lanjutkan dengan hati-hati."</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 4b97299..2087907 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Heyrnartæki"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Para nýtt tæki"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Smelltu til að para nýtt tæki"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Tókst ekki að uppfæra forstillingu"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Opna fyrir hljóðnema tækisins?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Opna fyrir myndavél tækisins?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Opna fyrir myndavél og hljóðnema tækisins?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Gervihnöttur, léleg tenging"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Gervihnöttur, góð tenging"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Gervihnöttur, tenging tiltæk"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Vinnusnið"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Þetta er ekki allra"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Fínstillingar kerfisviðmóts gera þér kleift að fínstilla og sérsníða notendaviðmót Android. Þessir tilraunaeiginleikar geta breyst, bilað eða horfið í síðari útgáfum. Gakktu því hægt um gleðinnar dyr."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 30bdfae..32f72fd 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellitare, connessione debole"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellitare, connessione buona"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitare, connessione disponibile"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profilo di lavoro"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Il divertimento riservato a pochi eletti"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"L\'Ottimizzatore UI di sistema mette a disposizione altri metodi per modificare e personalizzare l\'interfaccia utente di Android. Queste funzioni sperimentali potrebbero cambiare, interrompersi o scomparire nelle versioni successive. Procedi con cautela."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index bc1d91f..13f2e50 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"לוויין, חיבור באיכות ירודה"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"לוויין, חיבור באיכות טובה"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"לוויין, יש חיבור זמין"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"פרופיל עבודה"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"מהנה בשביל חלק מהאנשים, אבל לא בשביל כולם"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‏התכונה System UI Tuner מספקת לך דרכים נוספות להתאים אישית את ממשק המשתמש של Android. התכונות הניסיוניות האלה עשויות להשתנות, לא לעבוד כראוי או להיעלם בגרסאות עתידיות. יש להמשיך בזהירות."</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b587f40..b31c01c 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"衛生、接続不安定"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛生、接続状態良好"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛生、接続利用可能"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"仕事用プロファイル"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"一部の方のみお楽しみいただける限定公開ツール"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"システムUI調整ツールでは、Androidユーザーインターフェースの調整やカスタマイズを行えます。これらの試験運用機能は今後のリリースで変更となったり、中止となったり、削除されたりする可能性がありますのでご注意ください。"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index ff11d85..654acef 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"სუსტი სატელიტური კავშირი"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"კარგი სატელიტური კავშირი"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ხელმისაწვდომია სატელიტური კავშირი"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"სამსახურის პროფილი"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ზოგისთვის გასართობია, მაგრამ არა ყველასთვის"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"სისტემის UI ტუნერი გაძლევთ დამატებით გზებს Android-ის სამომხმარებლო ინტერფეისის პარამეტრების დაყენებისთვის. ეს ექსპერიმენტული მახასიათებლები შეიძლება შეიცვალოს, შეწყდეს ან გაქრეს მომავალ ვერსიებში. სიფრთხილით გააგრძელეთ."</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 995a796..0fda9f1 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Жерсерік, байланыс нашар."</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Жерсерік, байланыс жақсы."</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Жерсерік, байланыс бар."</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Жұмыс профилі"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Кейбіреулерге қызық, бірақ барлығына емес"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Жүйелік пайдаланушылық интерфейс тюнері Android пайдаланушылық интерфейсін реттеудің қосымша жолдарын береді. Бұл эксперименттік мүмкіндіктер болашақ шығарылымдарда өзгеруі, бұзылуы немесе жоғалуы мүмкін. Сақтықпен жалғастырыңыз."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index adcd3d6..262d87b 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ផ្កាយរណប ការតភ្ជាប់ខ្សោយ"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ផ្កាយរណប មានការតភ្ជាប់ល្អ"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ផ្កាយរណប អាចតភ្ជាប់បាន"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"កម្រងព័ត៌មានការងារ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ល្អសម្រាប់អ្នកប្រើមួយចំនួន តែមិនសម្រាប់គ្រប់គ្នាទេ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"កម្មវិធីសម្រួល UI ប្រព័ន្ធផ្តល់ជូនអ្នកនូវមធ្យោបាយបន្ថែមទៀតដើម្បីកែសម្រួល និងប្តូរចំណុចប្រទាក់អ្នកប្រើ Android តាមបំណង។ លក្ខណៈពិសេសសាកល្បងនេះអាចនឹងផ្លាស់ប្តូរ បំបែក ឬបាត់បង់បន្ទាប់ពីការចេញផ្សាយនាពេលអនាគត។ សូមបន្តដោយប្រុងប្រយ័ត្ន។"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index ca22ba1..14644cf 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"ಹಿಯರಿಂಗ್ ಸಾಧನಗಳು"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"ಹೊಸ ಸಾಧನವನ್ನು ಪೇರ್ ಮಾಡಿ"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"ಪ್ರಿಸೆಟ್ ಅನ್ನು ಅಪ್‌ಡೇಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"ಸಾಧನದ ಮೈಕ್ರೋಫೋನ್ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"ಸಾಧನದ ಕ್ಯಾಮರಾ ನಿರ್ಬಂಧವನ್ನು ತೆಗೆಯಬೇಕೆ?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"ಸಾಧನದ ಕ್ಯಾಮರಾ ಮತ್ತು ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ಅನ್‍ಬ್ಲಾಕ್ ಮಾಡಬೇಕೇ?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ಸ್ಯಾಟಲೈಟ್‌, ಕನೆಕ್ಷನ್ ಕಳಪೆಯಾಗಿದೆ"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ಸ್ಯಾಟಲೈಟ್‌, ಕನೆಕ್ಷನ್ ಉತ್ತಮವಾಗಿದೆ"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಲಭ್ಯವಿದೆ"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ಕೆಲವರಿಗೆ ಮೋಜು ಆಗಿದೆ ಎಲ್ಲರಿಗೆ ಇಲ್ಲ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"ಸಿಸ್ಟಂ UI ಟ್ಯೂನರ್ ನಿಮಗೆ Android ಬಳಕೆದಾರ ಅಂತರಸಂಪರ್ಕವನ್ನು ಸರಿಪಡಿಸಲು ಮತ್ತು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ಹೆಚ್ಚುವರಿ ಮಾರ್ಗಗಳನ್ನು ನೀಡುತ್ತದೆ. ಈ ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯಗಳು ಭವಿಷ್ಯದ ಬಿಡುಗಡೆಗಳಲ್ಲಿ ಬದಲಾಗಬಹುದು, ವಿರಾಮವಾಗಬಹುದು ಅಥವಾ ಕಾಣಿಸಿಕೊಳ್ಳದಿರಬಹುದು. ಎಚ್ಚರಿಕೆಯಿಂದ ಮುಂದುವರಿಯಿರಿ."</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 4e7c4d0..94cddf0 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"위성, 연결 상태 나쁨"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"위성, 연결 상태 양호"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"위성, 연결 가능"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"직장 프로필"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"마음에 들지 않을 수도 있음"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"시스템 UI 튜너를 사용하면 Android 사용자 인터페이스를 변경 및 맞춤설정할 수 있습니다. 이러한 실험실 기능은 향후 출시 버전에서는 변경되거나 다운되거나 사라질 수 있습니다. 신중하게 진행하시기 바랍니다."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 1d005fb..1561ac3 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Спутник, байланыш начар"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спутник, байланыш жакшы"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спутник, байланыш бар"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Жумуш профили"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Баарына эле жага бербейт"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android колдонуучу интерфейсин жөнгө салып жана ыңгайлаштыруунун кошумча ыкмаларын сунуштайт. Бул сынамык функциялар кийинки чыгарылыштарда өзгөрүлүп, бузулуп же жоголуп кетиши мүмкүн. Абайлап колдонуңуз."</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index f95bb8e..0370454 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ດາວທຽມ, ການເຊື່ອມຕໍ່ບໍ່ດີ"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ດາວທຽມ, ການເຊື່ອມຕໍ່ດີ"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ດາວທຽມ, ການເຊື່ອມຕໍ່ທີ່ພ້ອມນຳໃຊ້"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ມ່ວນຊື່ນສຳລັບບາງຄົນ ແຕ່ບໍ່ແມ່ນສຳລັບທຸກຄົນ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner ໃຫ້ທ່ານມີວິທີພິເສດຕື່ມອີກໃນການປັບປ່ຽນ ແລະຕົບແຕ່ງສ່ວນຕໍ່ປະສານຜູ້ໃຊ້ຂອງ Android. ຄຸນສົມບັດທົດລອງໃຊ້ເຫຼົ່ານີ້ອາດຈະປ່ຽນແປງ, ຢຸດເຊົາ ຫຼືຫາຍໄປໃນການວາງຈຳໜ່າຍໃນອະນາຄົດ. ຈົ່ງດຳເນີນຕໍ່ດ້ວຍຄວາມລະມັດລະວັງ."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 040294f..088a9fc 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Palydovas, prastas ryšys"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Palydovas, geras ryšys"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Palydovas, pasiekiamas ryšys"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Darbo profilis"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Smagu, bet ne visada"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Sistemos naudotojo sąsajos derinimo priemonė suteikia papildomų galimybių pagerinti ir tinkinti „Android“ naudotojo sąsają. Šios eksperimentinės funkcijos gali pasikeisti, nutrūkti ar išnykti iš būsimų laidų. Tęskite atsargiai."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index da58f33..09f0050 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelīts, vājš savienojums"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelīts, labs savienojums"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelīts, ir pieejams savienojums"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Darba profils"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Jautri dažiem, bet ne visiem"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Sistēmas saskarnes regulators sniedz papildu veidus, kā mainīt un pielāgot Android lietotāja saskarni. Nākamajās versijās šīs eksperimentālās funkcijas var tikt mainītas, bojātas vai to darbība var tikt pārtraukta. Turpinot esiet uzmanīgs."</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 2faf243..abac1ad 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Слаба сателитска врска"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Добра сателитска врска"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Достапна е сателитска врска"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Работен профил"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Забава за некои, но не за сите"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Адаптерот на УИ на системот ви дава дополнителни начини за дотерување и приспособување на корисничкиот интерфејс на Android. Овие експериментални функции можеби ќе се изменат, расипат или ќе исчезнат во следните изданија. Продолжете со претпазливост."</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 2fd4411..5bf98b5 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"സാറ്റലൈറ്റ്, മോശം കണക്ഷൻ"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"സാറ്റലൈറ്റ്, മികച്ച കണക്ഷൻ"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"സാറ്റലൈറ്റ്, കണക്ഷൻ ലഭ്യമാണ്"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ചിലർക്ക് വിനോദം, എന്നാൽ എല്ലാവർക്കുമില്ല"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Android ഉപയോക്തൃ ഇന്റർഫേസ് ആവശ്യമുള്ള രീതിയിൽ മാറ്റുന്നതിനും ഇഷ്ടാനുസൃതമാക്കുന്നതിനും സിസ്റ്റം UI ട്യൂണർ നിങ്ങൾക്ക് അധിക വഴികൾ നൽകുന്നു. ഭാവി റിലീസുകളിൽ ഈ പരീക്ഷണാത്മക ഫീച്ചറുകൾ മാറ്റുകയോ നിർത്തുകയോ അപ്രത്യക്ഷമാവുകയോ ചെയ്തേക്കാം. ശ്രദ്ധയോടെ മുന്നോട്ടുപോകുക."</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 94cdf4c..608492a 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Хиймэл дагуул, холболт муу байна"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Хиймэл дагуул, холболт сайн байна"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Хиймэл дагуул, холболт боломжтой"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Ажлын профайл"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Зарим хүнд хөгжилтэй байж болох ч бүх хүнд тийм биш"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Системийн UI Tохируулагч нь Android хэрэглэгчийн интерфэйсийг тааруулах, өөрчлөх нэмэлт аргыг зааж өгөх болно. Эдгээр туршилтын тохиргоо нь цаашид өөрчлөгдөх, эвдрэх, алга болох магадлалтай. Үйлдлийг болгоомжтой хийнэ үү."</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index dd53db5..e83cc4e 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"सॅटेलाइट, खराब कनेक्शन"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"सॅटेलाइट, चांगले कनेक्शन"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सॅटेलाइट, कनेक्शन उपलब्ध"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाईल"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"सर्वांसाठी नाही तर काहींसाठी मजेदार असू शकते"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनर आपल्‍याला Android यूझर इंटरफेस ट्विक आणि कस्टमाइझ करण्‍याचे अनेक प्रकार देते. ही प्रयोगात्मक वैशिष्‍ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्‍यातील रिलीज मध्‍ये कदाचित दिसणार नाहीत. सावधगिरी बाळगून पुढे सुरू ठेवा."</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 6b858a4..ad0c440 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, sambungan yang lemah"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, sambungan yang baik"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, sambungan tersedia"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Menarik untuk sesetengah orang tetapi bukan untuk semua"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Penala UI Sistem memberi anda cara tambahan untuk mengolah dan menyesuaikan antara muka Android. Ciri eksperimen ini boleh berubah, rosak atau hilang dalam keluaran masa hadapan. Teruskan dengan berhati-hati."</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 2472d1f..078bfd7 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု မကောင်းပါ"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ကောင်းသည်"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ရနိုင်သည်"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"အလုပ် ပရိုဖိုင်"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"အချို့သူများ အတွက် ပျော်စရာ ဖြစ်ပေမဲ့ အားလုံး အတွက် မဟုတ်ပါ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"စနစ် UI Tuner က သင့်အတွက် Android အသုံးပြုသူ အင်တာဖေ့စ်ကို ပြောင်းရန်နှင့် စိတ်ကြိုက်ပြုလုပ်ရန် နည်းလမ်း အပိုများကို သင့်အတွက် စီစဉ်ပေးသည်။ အနာဂတ်ဗားရှင်းများတွင် ဤစမ်းသပ်အင်္ဂါရပ်များမှာ ပြောင်းလဲ၊ ပျက်စီး သို့မဟုတ် ပျောက်ကွယ်သွားနိုင်သည်။ သတိဖြင့် ရှေ့ဆက်ပါ။"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 5bc2fe5..2634bd3 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellitt – dårlig tilkobling"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellitt – god tilkobling"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitt – tilkobling tilgjengelig"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Work-profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Gøy for noen – ikke for alle"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Med System UI Tuner har du flere måter å justere og tilpasse Android-brukergrensesnittet på. Disse eksperimentelle funksjonene kan endres, avbrytes eller fjernes i fremtidige utgivelser. Fortsett med forbehold."</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index f52466c..7f81a5f 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"स्याटलाइट, खराब कनेक्सन"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"स्याटलाइट, राम्रो कनेक्सन"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"स्याटलाइट, कनेक्सन उपलब्ध छ"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाइल"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"केहीका लागि रमाइलो हुन्छ तर सबैका लागि होइन"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनरले तपाईँलाई Android प्रयोगकर्ता इन्टरफेस आफू अनुकूल गर्न र ट्विक गर्न थप तरिकाहरू प्रदान गर्छ। यी प्रयोगात्मक सुविधाहरू भावी विमोचनमा परिवर्तन हुन, बिग्रिन वा हराउन सक्ने छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 61a323d4..d377e01 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -77,6 +77,7 @@
     <color name="biometric_dialog_gray">#ffcccccc</color>
     <color name="biometric_dialog_accent">@color/material_dynamic_primary70</color>
     <color name="biometric_dialog_error">#fff28b82</color> <!-- red 300 -->
+    <color name="biometric_dialog_face_checkmark">#5bb974</color> <!-- green 400 -->
 
     <color name="GM2_green_500">#FF41Af6A</color>
     <color name="GM2_blue_500">#5195EA</color>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 7a37aa0..78566b8 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -656,6 +656,8 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelliet, slechte verbinding"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliet, goede verbinding"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding beschikbaar"</string>
+    <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Verbonden met satelliet"</string>
+    <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Niet verbonden met satelliet"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Leuk voor sommige gebruikers, maar niet voor iedereen"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Met Systeem-UI-tuner beschikt u over extra manieren om de Android-gebruikersinterface aan te passen. Deze experimentele functies kunnen veranderen, vastlopen of verdwijnen in toekomstige releases. Ga voorzichtig verder."</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 7e8ee6f..03c7cf5 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ସାଟେଲାଇଟ, ଦୁର୍ବଳ କନେକ୍ସନ"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ସାଟେଲାଇଟ, ଭଲ କନେକ୍ସନ"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ସାଟେଲାଇଟ, କନେକ୍ସନ ଉପଲବ୍ଧ"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"କେତେକଙ୍କ ପାଇଁ ମଜାଦାର, କିନ୍ତୁ ସମସ୍ତଙ୍କ ପାଇଁ ନୁହେଁ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Android ୟୁଜର୍‍ ଇଣ୍ଟରଫେସ୍‍ ବଦଳାଇବାକୁ ତଥା ନିଜ ପସନ୍ଦ ଅନୁଯାୟୀ କରିବାକୁ ସିଷ୍ଟମ୍‍ UI ଟ୍ୟୁନର୍‍ ଆପଣଙ୍କୁ ଅତିରିକ୍ତ ଉପାୟ ପ୍ରଦାନ କରେ। ଏହି ପରୀକ୍ଷାମୂଳକ ସୁବିଧାମାନ ବଦଳିପାରେ, ଭାଙ୍ଗିପାରେ କିମ୍ବା ଭବିଷ୍ୟତର ରିଲିଜ୍‌ଗୁଡ଼ିକରେ ନଦେଖାଯାଇପାରେ। ସତର୍କତାର ସହ ଆଗକୁ ବଢ଼ନ୍ତୁ।"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index df823cf..6b88f29 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਖਰਾਬ ਹੈ"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਵਧੀਆ ਹੈ"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਉਪਲਬਧ ਹੈ"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"ਕੁਝ ਵਾਸਤੇ ਤਾਂ ਮਜ਼ੇਦਾਰ ਹੈ ਲੇਕਿਨ ਸਾਰਿਆਂ ਵਾਸਤੇ ਨਹੀਂ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"ਸਿਸਟਮ UI ਟਿਊਨਰ ਤੁਹਾਨੂੰ Android ਵਰਤੋਂਕਾਰ ਇੰਟਰਫ਼ੇਸ ਤਬਦੀਲ ਕਰਨ ਅਤੇ ਵਿਉਂਤਬੱਧ ਕਰਨ ਲਈ ਵਾਧੂ ਤਰੀਕੇ ਦਿੰਦਾ ਹੈ। ਇਹ ਪ੍ਰਯੋਗਾਤਮਿਕ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਭਵਿੱਖ ਦੀ ਰੀਲੀਜ਼ ਵਿੱਚ ਬਦਲ ਸਕਦੀਆਂ ਹਨ, ਟੁੱਟ ਸਕਦੀਆਂ ਹਨ, ਜਾਂ ਅਲੋਪ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਸਾਵਧਾਨੀ ਨਾਲ ਅੱਗੇ ਵੱਧੋ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index f6468af..d10d5f8 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Urządzenia słuchowe"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Sparuj nowe urządzenie"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Kliknij, aby sparować nowe urządzenie"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nie udało się zaktualizować gotowego ustawienia"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Odblokować mikrofon urządzenia?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Odblokować aparat urządzenia?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Odblokować aparat i mikrofon urządzenia?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelita – połączenie słabe"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelita – połączenie dobre"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelita – połączenie dostępne"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil służbowy"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Dobra zabawa, ale nie dla każdego"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Kalibrator System UI udostępnia dodatkowe sposoby dostrajania i dostosowywania interfejsu Androida. Te eksperymentalne funkcje mogą się zmienić, popsuć lub zniknąć w przyszłych wersjach. Zachowaj ostrożność."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index a1c72dc..d0f70ed 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, conexão ruim"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, conexão boa"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index eadb5e54..7889e0b 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -656,6 +656,8 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, ligação fraca"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, boa ligação"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, ligação disponível"</string>
+    <string name="satellite_connected_carrier_text" msgid="7942466244369263272">"Ligação de satélite estabelecida"</string>
+    <string name="satellite_not_connected_carrier_text" msgid="3471375076594005077">"Não tem uma ligação de satélite estabelecida"</string>
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"O Sintonizador da interface do sistema disponibiliza-lhe formas adicionais ajustar e personalizar a interface do utilizador do Android. Estas funcionalidades experimentais podem ser alteradas, deixar de funcionar ou desaparecer em versões futuras. Prossiga com cuidado."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index a1c72dc..d0f70ed 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satélite, conexão ruim"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, conexão boa"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index e53b4a4..8e4b752 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, conexiune slabă"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, conexiune bună"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, conexiune disponibilă"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil de serviciu"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Distractiv pentru unii, dar nu pentru toată lumea"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner oferă modalități suplimentare de a ajusta și a personaliza interfața de utilizare Android. Aceste funcții experimentale pot să se schimbe, să se blocheze sau să dispară din versiunile viitoare. Continuă cu prudență."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 8f6d7a8..d8d038e 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Спутниковая связь, плохое качество соединения"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спутниковая связь, хорошее качество соединения"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступно соединение по спутниковой связи"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Рабочий профиль"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Внимание!"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner позволяет настраивать интерфейс устройства Android по вашему вкусу. В будущем эта экспериментальная функция может измениться, перестать работать или исчезнуть."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index afb5755..5082174 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"චන්ද්‍රිකාව, දුර්වල සම්බන්ධතාවය"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"චන්ද්‍රිකාව, හොඳ සම්බන්ධතාවයක්"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"චන්ද්‍රිකාව, සම්බන්ධතාවය තිබේ"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"කාර්යාල පැතිකඩ"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"සමහරක් දේවල් වලට විනෝදයි, නමුත් සියල්ලටම නොවේ"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"පද්ධති UI සුසරකය ඔබට Android පරිශීලක අතුරු මුහුණත වෙනස් කිරීමට හෝ අභිරුචිකරණය කිරීමට අමතර ක්‍රම ලබා දේ. මෙම පර්යේෂණාත්මක අංග ඉදිරි නිකුත් වීම් වල වෙනස් වීමට, වැඩ නොකිරීමට, හෝ නැතිවීමට හැක. ප්‍රවේශමෙන් ඉදිරියට යන්න."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 453dd44..ffc9f27 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slabá kvalita pripojenia"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobrá kvalita pripojenia"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, pripojenie je k dispozícii"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovný profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Pri používaní tuneru postupujte opatrne"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Tuner používateľského rozhrania systému poskytujte ďalšie spôsoby ladenia a prispôsobenia používateľského rozhrania Android. Tieto experimentálne funkcie sa môžu v budúcich verziách zmeniť, ich poskytovanie môže byť prerušené alebo môžu byť odstránené. Pokračujte opatrne."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 27c376a..515286c 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satelit, slaba povezava"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra povezava"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, povezava je na voljo"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Delovni profil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Zabavno za nekatere, a ne za vse"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Uglaševalnik uporabniškega vmesnika sistema vam omogoča dodatne načine za spreminjanje in prilagajanje uporabniškega vmesnika Android. Te poskusne funkcije lahko v prihodnjih izdajah kadar koli izginejo, se spremenijo ali pokvarijo. Bodite previdni."</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 071eda7..99e5a7b 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Sateliti. Lidhje e dobët"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Sateliti. Lidhje e mirë"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sateliti. Ofrohet lidhje"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profili i punës"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Argëtim për disa, por jo për të gjithë!"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit të jep mënyra shtesë për të tërhequr dhe personalizuar ndërfaqen Android të përdoruesit. Këto funksione eksperimentale mund të ndryshojnë, prishen ose zhduken në versionet e ardhshme. Vazhdo me kujdes."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 233e516..e96d493 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Слушни апарати"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Упари нови уређај"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Кликните да бисте упарили нов уређај"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ажурирање задатих подешавања није успело"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Желите да одблокирате микрофон уређаја?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Желите да одблокирате камеру уређаја?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Желите да одблокирате камеру и микрофон уређаја?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Сателит, веза је лоша"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Сателит, веза је добра"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, веза је доступна"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Пословни профил"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Забава за неке, али не за све"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Тјунер за кориснички интерфејс система вам пружа додатне начине за подешавање и прилагођавање Android корисничког интерфејса. Ове експерименталне функције могу да се промене, откажу или нестану у будућим издањима. Будите опрезни."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 579f526..7a5fa65 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellit, dålig anslutning"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit, bra anslutning"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, anslutning tillgänglig"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Jobbprofil"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Kul för vissa, inte för alla"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Du kan använda inställningarna för systemgränssnitt för att justera användargränssnittet i Android. Dessa experimentfunktioner kan när som helst ändras, sluta fungera eller försvinna. Använd med försiktighet."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index bc7b016..9dae421 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Vifaa vya kusikilizia"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Unganisha kifaa kipya"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Bofya ili uunganishe kifaa kipya"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Imeshindwa kusasisha mipangilio iliyowekwa mapema"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Ungependa kuwacha kuzuia maikrofoni ya kifaa?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Ungependa kuacha kuzuia kamera ya kifaa?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Ungependa kuwacha kuzuia kamera na maikrofoni ya kifaa?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Setilaiti, muunganisho hafifu"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Setilaiti, muunganisho thabiti"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Setilaiti, muunganisho unapatikana"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Wasifu wa kazini"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Kinafurahisha kwa baadhi ya watu lakini si wote"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Kirekebishi cha kiolesura cha mfumo kinakupa njia zaidi za kugeuza na kubadilisha kiolesura cha Android ili kikufae. Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index b2c83dc..b418396 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"சாட்டிலைட், மோசமான இணைப்பு"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"சாட்டிலைட், நிலையான இணைப்பு"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"சாட்டிலைட், இணைப்பு கிடைக்கிறது"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"பணிக் கணக்கு"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"சில வேடிக்கையாக இருந்தாலும் கவனம் தேவை"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner, Android பயனர் இடைமுகத்தை மாற்றவும் தனிப்பயனாக்கவும் கூடுதல் வழிகளை வழங்குகிறது. இந்தப் பரிசோதனைக்குரிய அம்சங்கள் எதிர்கால வெளியீடுகளில் மாற்றப்படலாம், இடைநிறுத்தப்படலாம் அல்லது தோன்றாமல் போகலாம். கவனத்துடன் தொடரவும்."</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 5cd1341..a0a29d0 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"శాటిలైట్, కనెక్షన్ సరిగా లేదు"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"శాటిలైట్, కనెక్షన్ బాగుంది"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"శాటిలైట్, కనెక్షన్ అందుబాటులో ఉంది"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"ఆఫీస్ ప్రొఫైల్‌"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"కొందరికి సరదాగా ఉంటుంది కానీ అందరికీ అలాగే ఉండదు"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"సిస్టమ్ UI ట్యూనర్ Android వినియోగదారు ఇంటర్‌ఫేస్‌ను మెరుగుపరచడానికి మరియు అనుకూలంగా మార్చడానికి మీకు మరిన్ని మార్గాలను అందిస్తుంది. ఈ ప్రయోగాత్మక లక్షణాలు భవిష్యత్తు విడుదలల్లో మార్పుకు లోనవ్వచ్చు, తాత్కాలికంగా లేదా పూర్తిగా నిలిపివేయవచ్చు. జాగ్రత్తగా కొనసాగండి."</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 544844d..0ef447e 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"ดาวเทียม, การเชื่อมต่อไม่ดี"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ดาวเทียม, การเชื่อมต่อดี"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ดาวเทียม, การเชื่อมต่อที่พร้อมใช้งาน"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"โปรไฟล์งาน"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"เพลิดเพลินกับบางส่วนแต่ไม่ใช่ทั้งหมด"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"ตัวรับสัญญาณ UI ระบบช่วยให้คุณมีวิธีพิเศษในการปรับแต่งและกำหนดค่าส่วนติดต่อผู้ใช้ Android ฟีเจอร์รุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 13e4bf8..975820a 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Satellite, mahina ang koneksyon"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, malakas ang koneksyon"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, may koneksyon"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Profile sa trabaho"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Masaya para sa ilan ngunit hindi para sa lahat"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Nagbibigay sa iyo ang Tuner ng System UI ng mga karagdagang paraan upang baguhin at i-customize ang user interface ng Android. Ang mga pang-eksperimentong feature na ito ay maaaring magbago, masira o mawala sa mga pagpapalabas sa hinaharap. Magpatuloy nang may pag-iingat."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 30b6ce4..5b10259 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Uydu, bağlantı zayıf"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Uydu, bağlantı güçlü"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Uydu, bağlantı mevcut"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Bazıları için eğlenceliyken diğerleri için olmayabilir"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Sistem Kullanıcı Arayüzü Ayarlayıcı, Android kullanıcı arayüzünde değişiklikler yapmanız ve arayüzü özelleştirmeniz için ekstra yollar sağlar. Bu deneysel özellikler değişebilir, bozulabilir veya gelecekteki sürümlerde yer almayabilir. Dikkatli bir şekilde devam edin."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index e1d768e..071313f 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Погане з’єднання із супутником"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Хороше з’єднання із супутником"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступне з’єднання із супутником"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Робочий профіль"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Це цікаво, але будьте обачні"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner пропонує нові способи налаштувати та персоналізувати інтерфейс користувача Android. Ці експериментальні функції можуть змінюватися, не працювати чи зникати в майбутніх версіях. Будьте обачні."</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 16b40bf..e1b1fa4 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"سیٹلائٹ، کنکشن خراب ہے"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"سیٹلائٹ، کنکشن اچھا ہے"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"سیٹلائٹ، کنکشن دستیاب ہے"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"دفتری پروفائل"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"کچھ کیلئے دلچسپ لیکن سبھی کیلئے نہیں"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"‏سسٹم UI ٹیونر Android صارف انٹر فیس میں ردوبدل کرنے اور اسے حسب ضرورت بنانے کیلئے آپ کو اضافی طریقے دیتا ہے۔ یہ تجرباتی خصوصیات مستقبل کی ریلیزز میں تبدیل ہو سکتی، رک سکتی یا غائب ہو سکتی ہیں۔ احتیاط کے ساتھ آگے بڑھیں۔"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 76694df..27145a6 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -371,8 +371,7 @@
     <string name="quick_settings_hearing_devices_dialog_title" msgid="9004774017688484981">"Eshitish qurilmalari"</string>
     <string name="quick_settings_pair_hearing_devices" msgid="5987105102207447322">"Yangi qurilmani ulash"</string>
     <string name="accessibility_hearing_device_pair_new_device" msgid="8440082580186130090">"Yangi qurilmani ulash uchun bosing"</string>
-    <!-- no translation found for hearing_devices_presets_error (350363093458408536) -->
-    <skip />
+    <string name="hearing_devices_presets_error" msgid="350363093458408536">"Andoza yangilanmadi"</string>
     <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"Qurilma mikrofoni blokdan chiqarilsinmi?"</string>
     <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"Qurilma kamerasi blokdan chiqarilsinmi?"</string>
     <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"Qurilma kamerasi va mikrofoni blokdan chiqarilsinmi?"</string>
@@ -656,6 +655,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Sputnik, aloqa sifati past"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Sputnik, aloqa sifati yaxshi"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sputnik, aloqa mavjud"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Ish profili"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Diqqat!"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner yordamida siz Android foydalanuvchi interfeysini tuzatish va o‘zingizga moslashtirishingiz mumkin. Ushbu tajribaviy funksiyalar o‘zgarishi, buzilishi yoki keyingi versiyalarda olib tashlanishi mumkin. Ehtiyot bo‘lib davom eting."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 41066f9..84447fa 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Kết nối vệ tinh kém"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Kết nối vệ tinh tốt"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Hiện có kết nối vệ tinh"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Hồ sơ công việc"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Thú vị đối với một số người nhưng không phải tất cả"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Bộ điều hướng giao diện người dùng hệ thống cung cấp thêm cho bạn những cách chỉnh sửa và tùy chỉnh giao diện người dùng Android. Những tính năng thử nghiệm này có thể thay đổi, hỏng hoặc biến mất trong các phiên bản tương lai. Hãy thận trọng khi tiếp tục."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 60a46d60..eb928f0 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"卫星,连接质量不佳"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"卫星,连接质量良好"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"卫星,可连接"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"工作资料"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"并不适合所有用户"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"系统界面调节工具可让您以更多方式调整及定制 Android 界面。在日后推出的版本中,这些实验性功能可能会变更、失效或消失。操作时请务必谨慎。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 995129e..4ec1b58 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"衛星,連線質素唔好"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛星,連線質素好"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可以連線"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"工作設定檔"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"這只是測試版本,並不包含完整功能"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"使用者介面調諧器讓你以更多方法修改和自訂 Android 使用者介面。但請小心,這些實驗功能可能會在日後發佈時更改、分拆或消失。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index d18f828..52a1917 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"衛星,連線品質不佳"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛星,連線品質良好"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可連線"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"工作資料夾"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"有趣與否,見仁見智"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"系統使用者介面調整精靈可讓你透過其他方式,調整及自訂 Android 使用者介面。這些實驗性功能隨著版本更新可能會變更、損壞或消失,執行時請務必謹慎。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index a5caa3d..c96be0e 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -656,6 +656,10 @@
     <string name="accessibility_status_bar_satellite_poor_connection" msgid="5231478574952724160">"Isathelayithi, uxhumano olungalungile"</string>
     <string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Isethelayithi, uxhumano oluhle"</string>
     <string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Isethelayithi, uxhumano luyatholakala"</string>
+    <!-- no translation found for satellite_connected_carrier_text (7942466244369263272) -->
+    <skip />
+    <!-- no translation found for satellite_not_connected_carrier_text (3471375076594005077) -->
+    <skip />
     <string name="accessibility_managed_profile" msgid="4703836746209377356">"Iphrofayela yomsebenzi"</string>
     <string name="tuner_warning_title" msgid="7721976098452135267">"Kuyajabulisa kwabanye kodwa hhayi bonke"</string>
     <string name="tuner_warning" msgid="1861736288458481650">"Isishuni se-UI sesistimu sikunika izindlela ezingeziwe zokuhlobisa nokwenza ngezifiso isixhumanisi sokubona se-Android. Lezi zici zesilingo zingashintsha, zephuke, noma zinyamalale ekukhishweni kwangakusasa. Qhubeka ngokuqaphela."</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 590dc68..ba59c2f9 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -140,6 +140,7 @@
     <color name="biometric_dialog_gray">#ff757575</color>
     <color name="biometric_dialog_accent">@color/material_dynamic_primary40</color>
     <color name="biometric_dialog_error">#ffd93025</color>                  <!-- red 600 -->
+    <color name="biometric_dialog_face_checkmark">#34A853</color> <!-- green 500 -->
 
     <!-- SFPS colors -->
     <color name="sfps_chevron_fill">@color/material_dynamic_primary90</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index df57f2a..1a85f8d4 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1094,9 +1094,9 @@
     <dimen name="remote_input_history_extra_height">60dp</dimen>
 
     <!-- Biometric Dialog values -->
-    <dimen name="biometric_dialog_face_icon_size">54dp</dimen>
-    <dimen name="biometric_dialog_fingerprint_icon_width">80dp</dimen>
-    <dimen name="biometric_dialog_fingerprint_icon_height">80dp</dimen>
+    <dimen name="biometric_dialog_face_icon_size">68dp</dimen>
+    <dimen name="biometric_dialog_fingerprint_icon_width">100dp</dimen>
+    <dimen name="biometric_dialog_fingerprint_icon_height">100dp</dimen>
     <dimen name="biometric_dialog_button_negative_max_width">160dp</dimen>
     <dimen name="biometric_dialog_button_positive_max_width">136dp</dimen>
     <dimen name="biometric_dialog_corner_size">28dp</dimen>
@@ -1793,9 +1793,9 @@
     the lockscreen -->
     <dimen name="communal_right_edge_swipe_region_width">40dp</dimen>
     <!-- Height of area at top of communal hub where swipes should open the notification shade -->
-    <dimen name="communal_top_edge_swipe_region_height">68dp</dimen>
+    <dimen name="communal_top_edge_swipe_region_height">64dp</dimen>
     <!-- Height of area at bottom of communal hub where swipes should open the bouncer -->
-    <dimen name="communal_bottom_edge_swipe_region_height">68dp</dimen>
+    <dimen name="communal_bottom_edge_swipe_region_height">140dp</dimen>
 
     <dimen name="drag_and_drop_icon_size">70dp</dimen>
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/UiBackground.java b/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/UiBackground.java
index bf2237a..3d37468 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/UiBackground.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/dagger/qualifiers/UiBackground.java
@@ -23,7 +23,6 @@
 
 import javax.inject.Qualifier;
 
-
 /**
  * An annotation for injecting instances related to UI operations off the main-thread.
  */
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java
index 9bead94..670feeb 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java
@@ -24,6 +24,8 @@
 import androidx.lifecycle.LifecycleEventObserver;
 import androidx.lifecycle.LifecycleOwner;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
@@ -33,8 +35,6 @@
 import java.util.Iterator;
 import java.util.List;
 
-import kotlinx.coroutines.CoroutineScope;
-
 /**
  * Base class for a condition that needs to be fulfilled in order for {@link Monitor} to inform
  * its callbacks.
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index 400f652..87b473f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -17,7 +17,6 @@
 package com.android.systemui.shared.rotation;
 
 import static android.content.pm.PackageManager.FEATURE_PC;
-import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
 import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.internal.view.RotationPolicy.NATURAL_ROTATION;
@@ -38,8 +37,6 @@
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
-import android.os.HandlerExecutor;
-import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.RemoteException;
 import android.os.SystemProperties;
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
index 5647b0b..3f34df7 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
@@ -49,6 +49,8 @@
 import com.android.systemui.telephony.TelephonyListenerManager;
 import com.android.systemui.util.kotlin.JavaAdapter;
 
+import kotlinx.coroutines.Job;
+
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
@@ -58,8 +60,6 @@
 
 import javax.inject.Inject;
 
-import kotlinx.coroutines.Job;
-
 /**
  * Controller that generates text including the carrier names and/or the status of all the SIM
  * interfaces in the device. Through a callback, the updates can be retrieved either as a list or
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index fb331b6..4af366c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -49,7 +49,6 @@
 
 import javax.inject.Inject;
 
-
 @SysUISingleton
 public class KeyguardDisplayManager {
     protected static final String TAG = "KeyguardDisplayManager";
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
index 75d925d..db14a0f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java
@@ -47,7 +47,6 @@
 
 import javax.inject.Inject;
 
-
 /** Controller for a {@link KeyguardSecurityView}. */
 public abstract class KeyguardInputViewController<T extends KeyguardInputView>
         extends ViewController<T> implements KeyguardSecurityView {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 26e91b6..641c5dd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -58,7 +58,6 @@
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 
-
 /**
  * Displays an alphanumeric (latin-1) key entry for the user to enter
  * an unlock password
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
index ec2999f..120045f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java
@@ -30,8 +30,8 @@
 import com.android.keyguard.KeyguardInputViewController.Factory;
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.keyguard.dagger.KeyguardBouncerScope;
-import com.android.systemui.res.R;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.res.R;
 import com.android.systemui.util.ViewController;
 
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index 151ca8a..d2221c2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -24,7 +24,6 @@
 
 import com.android.systemui.res.R;
 
-
 /**
  * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier.
  */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 519622e..167ab90 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -30,6 +30,8 @@
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT;
 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_TIMED;
 import static android.hardware.biometrics.BiometricConstants.LockoutMode;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
 import static android.hardware.biometrics.BiometricSourceType.FACE;
 import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
 import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
@@ -1238,9 +1240,9 @@
         boolean cameraPrivacyEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled(
                 SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE, SensorPrivacyManager.Sensors.CAMERA);
 
-        final boolean isHwUnavailable = msgId == FaceManager.FACE_ERROR_HW_UNAVAILABLE;
+        final boolean isHwUnavailable = msgId == FACE_ERROR_HW_UNAVAILABLE;
 
-        if (msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) {
+        if (msgId == FACE_ERROR_LOCKOUT_PERMANENT) {
             if (getFaceAuthInteractor() != null && getFaceAuthInteractor().isFaceAuthStrong()) {
                 updateFingerprintListeningState(BIOMETRIC_ACTION_STOP);
             }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java
index f746459..6b8673e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java
@@ -25,8 +25,8 @@
 import android.widget.ListPopupWindow;
 import android.widget.ListView;
 
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.res.R;
 
 /**
  * Custom user-switcher for use on the bouncer.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
index afeb0f8..9513c8e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardViewController.java
@@ -27,7 +27,6 @@
 import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor;
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
 
 /**
  *  Interface to control Keyguard View. It should be implemented by KeyguardViewManagers, which
diff --git a/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java
index cf2675b..a9fd340 100644
--- a/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java
@@ -83,14 +83,14 @@
 
 import dagger.Lazy;
 
+import kotlinx.coroutines.ExperimentalCoroutinesApi;
+
 import java.io.PrintWriter;
 import java.util.Objects;
 import java.util.function.Consumer;
 
 import javax.inject.Inject;
 
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
-
 /**
  * Controls when to show the LockIcon affordance (lock/unlocked icon or circle) on lock screen.
  *
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
index b57c2b5..786965a 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java
@@ -19,8 +19,8 @@
 import android.view.ViewGroup;
 
 import com.android.keyguard.KeyguardSecurityContainerController;
-import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.dagger.qualifiers.RootView;
 
 import dagger.BindsInstance;
 import dagger.Subcomponent;
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
index 37600da..8fb5204 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardStatusBarViewModule.java
@@ -17,8 +17,8 @@
 package com.android.keyguard.dagger;
 
 import com.android.keyguard.CarrierText;
-import com.android.systemui.res.R;
 import com.android.systemui.battery.BatteryMeterView;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.phone.KeyguardStatusBarView;
 import com.android.systemui.statusbar.phone.StatusBarLocation;
 import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 33f14d4..a42f4c2d 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -64,7 +64,6 @@
 import javax.inject.Inject;
 import javax.inject.Named;
 
-
 /**
  * Class to handle ugly dependencies throughout sysui until we determine the
  * long-term dependency injection solution.
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 086713f..57c1fd0 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -36,10 +36,9 @@
 import androidx.core.animation.AnimatorListenerAdapter;
 import androidx.core.animation.ObjectAnimator;
 
-import com.android.systemui.res.R;
-
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.jank.InteractionJankMonitor;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
index ab431d0..09526a3 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServicesDialog.java
@@ -37,11 +37,11 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
-import com.android.systemui.res.R;
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.systemui.res.R;
 
 import java.util.ArrayList;
 
diff --git a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
index 0f5f869..13b6672 100644
--- a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
@@ -24,7 +24,6 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.systemui.res.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.GuestResetOrExitSessionReceiver.ResetSessionDialogFactory;
@@ -32,6 +31,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.qs.QSUserSwitcherEvent;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
diff --git a/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java b/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java
index 161cb43..06d126c 100644
--- a/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/GuestSessionNotification.java
@@ -26,8 +26,8 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 
-import com.android.systemui.res.R;
 import com.android.internal.messages.nano.SystemMessageProto;
+import com.android.systemui.res.R;
 import com.android.systemui.util.NotificationChannels;
 
 import javax.inject.Inject;
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareBgDrawable.java b/packages/SystemUI/src/com/android/systemui/HardwareBgDrawable.java
index 0643d02..d3bda8e 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareBgDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareBgDrawable.java
@@ -23,8 +23,8 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LayerDrawable;
 
-import com.android.systemui.res.R;
 import com.android.settingslib.Utils;
+import com.android.systemui.res.R;
 
 public class HardwareBgDrawable extends LayerDrawable {
 
diff --git a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
index b9e412c..302ea39 100644
--- a/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/PluginInflateContainer.java
@@ -20,10 +20,10 @@
 import android.util.Log;
 import android.view.View;
 
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.plugins.ViewProvider;
+import com.android.systemui.res.R;
 
 /**
  * Define an interface or abstract class as follows that includes the
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java
index 83ad3c2..5160309 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapter.java
@@ -29,8 +29,8 @@
 
 import com.android.internal.accessibility.common.ShortcutConstants.AccessibilityFragmentType;
 import com.android.internal.accessibility.dialog.AccessibilityTarget;
-import com.android.systemui.res.R;
 import com.android.systemui.accessibility.floatingmenu.AccessibilityTargetAdapter.ViewHolder;
+import com.android.systemui.res.R;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuEduTooltipView.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuEduTooltipView.java
index 1ff9eb4..c4274ea 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuEduTooltipView.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuEduTooltipView.java
@@ -41,8 +41,8 @@
 import androidx.annotation.NonNull;
 
 import com.android.settingslib.Utils;
-import com.android.systemui.res.R;
 import com.android.systemui.recents.TriangleShape;
+import com.android.systemui.res.R;
 
 /**
  * The tooltip view shows the information about the operation of the anchor view {@link MenuView}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
index b8ff0c0..99be762 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt
@@ -112,6 +112,7 @@
         const val COLOR_INVERSION_TILE_SPEC = "inversion"
         const val FONT_SCALING_TILE_SPEC = "font_scaling"
         const val REDUCE_BRIGHTNESS_TILE_SPEC = "reduce_brightness"
+        const val ONE_HANDED_TILE_SPEC = "onehanded"
 
         @Provides
         @IntoMap
@@ -241,5 +242,19 @@
                     mapper,
                 )
             else StubQSTileViewModel
+
+        @Provides
+        @IntoMap
+        @StringKey(ONE_HANDED_TILE_SPEC)
+        fun provideOneHandedTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(ONE_HANDED_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = com.android.internal.R.drawable.ic_qs_one_handed_mode,
+                        labelRes = R.string.quick_settings_onehanded_label,
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
index e7e12ba..227e4db 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
@@ -19,6 +19,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 
 import static com.android.systemui.shared.Flags.bouncerAreaExclusion;
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
 
 import android.graphics.Rect;
 import android.graphics.Region;
@@ -37,7 +38,9 @@
 import androidx.lifecycle.LifecycleObserver;
 import androidx.lifecycle.LifecycleOwner;
 
+import com.android.systemui.Flags;
 import com.android.systemui.ambient.touch.dagger.InputSessionComponent;
+import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.DisplayId;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -69,6 +72,9 @@
     public String TAG = "DreamOverlayTouchMonitor";
     private final Executor mMainExecutor;
     private final Executor mBackgroundExecutor;
+
+    private final ConfigurationInteractor mConfigurationInteractor;
+
     private final Lifecycle mLifecycle;
     private Rect mExclusionRect = null;
 
@@ -82,6 +88,8 @@
                 }
             };
 
+    private Consumer<Rect> mMaxBoundsConsumer = rect -> mMaxBounds = rect;
+
 
     /**
      * Adds a new {@link TouchSessionImpl} to participate in receiving future touches and gestures.
@@ -262,6 +270,7 @@
      */
     private void startMonitoring() {
         stopMonitoring(true);
+
         if (bouncerAreaExclusion()) {
             mBackgroundExecutor.execute(() -> {
                 try {
@@ -340,8 +349,13 @@
                             if (!handler.isEnabled()) {
                                 continue;
                             }
-                            final Rect maxBounds = mDisplayHelper.getMaxBounds(ev.getDisplayId(),
-                                    TYPE_APPLICATION_OVERLAY);
+
+                            final Rect maxBounds =
+                                    Flags.ambientTouchMonitorListenToDisplayChanges()
+                                            ? mMaxBounds
+                                            : mDisplayHelper.getMaxBounds(ev.getDisplayId(),
+                                                    TYPE_APPLICATION_OVERLAY);
+
                             final Region initiationRegion = Region.obtain();
                             Rect exclusionRect = null;
                             if (bouncerAreaExclusion()) {
@@ -478,6 +492,8 @@
     private final int mDisplayId;
     private final IWindowManager mWindowManagerService;
 
+    private Rect mMaxBounds;
+
 
     /**
      * Designated constructor for {@link TouchMonitor}
@@ -500,6 +516,7 @@
             Lifecycle lifecycle,
             InputSessionComponent.Factory inputSessionFactory,
             DisplayHelper displayHelper,
+            ConfigurationInteractor configurationInteractor,
             Set<TouchHandler> handlers,
             IWindowManager windowManagerService,
             @DisplayId int displayId) {
@@ -511,6 +528,7 @@
         mLifecycle = lifecycle;
         mDisplayHelper = displayHelper;
         mWindowManagerService = windowManagerService;
+        mConfigurationInteractor = configurationInteractor;
     }
 
     /**
@@ -518,6 +536,9 @@
      */
     public void init() {
         mLifecycle.addObserver(mLifecycleObserver);
+        if (Flags.ambientTouchMonitorListenToDisplayChanges()) {
+            collectFlow(mLifecycle, mConfigurationInteractor.getMaxBounds(), mMaxBoundsConsumer);
+        }
     }
 
     private void isolate(Set<TouchSessionImpl> sessions) {
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionModule.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionModule.java
index 99dbdee..5875ffc 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionModule.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/InputSessionModule.java
@@ -28,7 +28,6 @@
 
 import javax.inject.Named;
 
-
 /**
  * Module for providing dependencies to {@link com.android.systemui.dreams.touch.InputSession}.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
index f9138b6..b0eddea 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistModule.java
@@ -26,11 +26,11 @@
 import com.android.internal.app.AssistUtils;
 import com.android.systemui.dagger.SysUISingleton;
 
-import javax.inject.Named;
-
 import dagger.Module;
 import dagger.Provides;
 
+import javax.inject.Named;
+
 /** Module for dagger injections related to the Assistant. */
 @Module
 public abstract class AssistModule {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
index dfff00b..e425f29 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
@@ -38,14 +38,14 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
 
+import dagger.Lazy;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Optional;
 
 import javax.inject.Inject;
 
-import dagger.Lazy;
-
 /** Class to monitor and report the state of the phone. */
 @SysUISingleton
 public final class PhoneStateMonitor {
diff --git a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
index 5b840b5..4f13e6f 100644
--- a/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java
@@ -30,14 +30,14 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarLocation;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.tuner.TunerService;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index fd0e7fc..1c17beb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -87,6 +87,8 @@
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -96,8 +98,6 @@
 
 import javax.inject.Provider;
 
-import kotlinx.coroutines.CoroutineScope;
-
 /**
  * Top level container/controller for the BiometricPrompt UI.
  *
@@ -230,9 +230,13 @@
         @Override
         public void onUseDeviceCredential() {
             mConfig.mCallback.onDeviceCredentialPressed(getRequestId());
-            mHandler.postDelayed(() -> {
+            if (constraintBp()) {
                 addCredentialView(false /* animatePanel */, true /* animateContents */);
-            }, mConfig.mSkipAnimation ? 0 : ANIMATE_CREDENTIAL_START_DELAY_MS);
+            } else {
+                mHandler.postDelayed(() -> {
+                    addCredentialView(false /* animatePanel */, true /* animateContents */);
+                }, mConfig.mSkipAnimation ? 0 : ANIMATE_CREDENTIAL_START_DELAY_MS);
+            }
 
             // TODO(b/313469218): Remove Config
             mConfig.mPromptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index b25c3da..fb718d3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -110,6 +110,9 @@
 
 import kotlin.Unit;
 
+import kotlinx.coroutines.CoroutineScope;
+import kotlinx.coroutines.ExperimentalCoroutinesApi;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -118,9 +121,6 @@
 
 import javax.inject.Inject;
 
-import kotlinx.coroutines.CoroutineScope;
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
-
 /**
  * Shows and hides the under-display fingerprint sensor (UDFPS) overlay, handles UDFPS touch events,
  * and toggles the UDFPS display mode.
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index 072fe47..a211147 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -87,7 +87,9 @@
          *
          * TODO(b/288175072): May be able to remove this once constraint layout is implemented
          */
-        view.visibility = View.INVISIBLE
+        if (!constraintBp()) {
+            view.visibility = View.INVISIBLE
+        }
         val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!!
 
         val textColorError =
@@ -102,6 +104,12 @@
         val descriptionView = view.requireViewById<TextView>(R.id.description)
         val customizedViewContainer =
             view.requireViewById<LinearLayout>(R.id.customized_view_container)
+        val udfpsGuidanceView =
+            if (constraintBp()) {
+                view.requireViewById<View>(R.id.panel)
+            } else {
+                backgroundView
+            }
 
         // set selected to enable marquee unless a screen reader is enabled
         logoView.isSelected =
@@ -226,8 +234,8 @@
             }
 
             lifecycleScope.launch {
-                viewModel.showBpWithoutIconForCredential.collect {
-                    if (!it) {
+                viewModel.showBpWithoutIconForCredential.collect { showWithoutIcon ->
+                    if (!showWithoutIcon) {
                         PromptIconViewBinder.bind(
                             iconView,
                             iconOverlayView,
@@ -428,7 +436,7 @@
                 }
 
                 // Talkback directional guidance
-                backgroundView.setOnHoverListener { _, event ->
+                udfpsGuidanceView.setOnHoverListener { _, event ->
                     launch {
                         viewModel.onAnnounceAccessibilityHint(
                             event,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
index f380746..d1ad783 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt
@@ -20,6 +20,7 @@
 import android.animation.AnimatorSet
 import android.animation.ValueAnimator
 import android.graphics.Outline
+import android.graphics.Rect
 import android.transition.AutoTransition
 import android.transition.TransitionManager
 import android.util.TypedValue
@@ -36,7 +37,6 @@
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.constraintlayout.widget.Guideline
 import androidx.core.animation.addListener
-import androidx.core.view.doOnAttach
 import androidx.core.view.doOnLayout
 import androidx.core.view.isGone
 import androidx.lifecycle.lifecycleScope
@@ -106,6 +106,52 @@
                     )
                     .toInt()
 
+            var currentSize: PromptSize? = null
+            var currentPosition: PromptPosition = PromptPosition.Bottom
+            panelView.outlineProvider =
+                object : ViewOutlineProvider() {
+                    override fun getOutline(view: View, outline: Outline) {
+                        when (currentPosition) {
+                            PromptPosition.Right -> {
+                                outline.setRoundRect(
+                                    0,
+                                    0,
+                                    view.width + cornerRadiusPx,
+                                    view.height,
+                                    cornerRadiusPx.toFloat()
+                                )
+                            }
+                            PromptPosition.Left -> {
+                                outline.setRoundRect(
+                                    -cornerRadiusPx,
+                                    0,
+                                    view.width,
+                                    view.height,
+                                    cornerRadiusPx.toFloat()
+                                )
+                            }
+                            PromptPosition.Top -> {
+                                outline.setRoundRect(
+                                    0,
+                                    -cornerRadiusPx,
+                                    view.width,
+                                    view.height,
+                                    cornerRadiusPx.toFloat()
+                                )
+                            }
+                            PromptPosition.Bottom -> {
+                                outline.setRoundRect(
+                                    0,
+                                    0,
+                                    view.width,
+                                    view.height + cornerRadiusPx,
+                                    cornerRadiusPx.toFloat()
+                                )
+                            }
+                        }
+                    }
+                }
+
             // ConstraintSets for animating between prompt sizes
             val mediumConstraintSet = ConstraintSet()
             mediumConstraintSet.clone(view as ConstraintLayout)
@@ -115,7 +161,9 @@
 
             val largeConstraintSet = ConstraintSet()
             largeConstraintSet.clone(mediumConstraintSet)
-            largeConstraintSet.constrainMaxWidth(R.id.panel, view.width)
+            largeConstraintSet.constrainMaxWidth(R.id.panel, 0)
+            largeConstraintSet.setGuidelineBegin(R.id.leftGuideline, 0)
+            largeConstraintSet.setGuidelineEnd(R.id.rightGuideline, 0)
 
             // TODO: Investigate better way to handle 180 rotations
             val flipConstraintSet = ConstraintSet()
@@ -138,65 +186,134 @@
                     }
                 }
 
-                fun roundCorners(size: PromptSize, position: PromptPosition) {
-                    var left = 0
-                    var top = 0
-                    var right = 0
-                    var bottom = 0
-                    when (size) {
-                        PromptSize.SMALL,
-                        PromptSize.MEDIUM ->
-                            when (position) {
-                                PromptPosition.Right -> {
-                                    left = 0
-                                    top = 0
-                                    right = view.width + cornerRadiusPx
-                                    bottom = view.height
+                view.repeatWhenAttached {
+                    lifecycleScope.launch {
+                        viewModel.iconPosition.collect { position ->
+                            if (position != Rect()) {
+                                val iconParams =
+                                    iconHolderView.layoutParams as ConstraintLayout.LayoutParams
+
+                                if (position.left != 0) {
+                                    iconParams.endToEnd = ConstraintSet.UNSET
+                                    iconParams.leftMargin = position.left
+                                    mediumConstraintSet.clear(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.END
+                                    )
+                                    mediumConstraintSet.connect(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.START,
+                                        ConstraintSet.PARENT_ID,
+                                        ConstraintSet.START
+                                    )
+                                    mediumConstraintSet.setMargin(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.START,
+                                        position.left
+                                    )
+                                    smallConstraintSet.clear(R.id.biometric_icon, ConstraintSet.END)
+                                    smallConstraintSet.connect(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.START,
+                                        ConstraintSet.PARENT_ID,
+                                        ConstraintSet.START
+                                    )
+                                    smallConstraintSet.setMargin(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.START,
+                                        position.left
+                                    )
                                 }
-                                PromptPosition.Left -> {
-                                    left = -cornerRadiusPx
-                                    top = 0
-                                    right = view.width
-                                    bottom = view.height
+                                if (position.top != 0) {
+                                    iconParams.bottomToBottom = ConstraintSet.UNSET
+                                    iconParams.topMargin = position.top
+                                    mediumConstraintSet.clear(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.BOTTOM
+                                    )
+                                    mediumConstraintSet.setMargin(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.TOP,
+                                        position.top
+                                    )
+                                    smallConstraintSet.clear(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.BOTTOM
+                                    )
+                                    smallConstraintSet.setMargin(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.TOP,
+                                        position.top
+                                    )
                                 }
-                                PromptPosition.Top -> {
-                                    left = 0
-                                    top = -cornerRadiusPx
-                                    right = panelView.width
-                                    bottom = view.height
+                                if (position.right != 0) {
+                                    iconParams.startToStart = ConstraintSet.UNSET
+                                    iconParams.rightMargin = position.right
+                                    mediumConstraintSet.clear(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.START
+                                    )
+                                    mediumConstraintSet.connect(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.END,
+                                        ConstraintSet.PARENT_ID,
+                                        ConstraintSet.END
+                                    )
+                                    mediumConstraintSet.setMargin(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.END,
+                                        position.right
+                                    )
+                                    smallConstraintSet.clear(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.START
+                                    )
+                                    smallConstraintSet.connect(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.END,
+                                        ConstraintSet.PARENT_ID,
+                                        ConstraintSet.END
+                                    )
+                                    smallConstraintSet.setMargin(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.END,
+                                        position.right
+                                    )
                                 }
-                                PromptPosition.Bottom -> {
-                                    left = 0
-                                    top = 0
-                                    right = panelView.width
-                                    bottom = view.height + cornerRadiusPx
+                                if (position.bottom != 0) {
+                                    iconParams.topToTop = ConstraintSet.UNSET
+                                    iconParams.bottomMargin = position.bottom
+                                    mediumConstraintSet.clear(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.TOP
+                                    )
+                                    mediumConstraintSet.setMargin(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.BOTTOM,
+                                        position.bottom
+                                    )
+                                    smallConstraintSet.clear(R.id.biometric_icon, ConstraintSet.TOP)
+                                    smallConstraintSet.setMargin(
+                                        R.id.biometric_icon,
+                                        ConstraintSet.BOTTOM,
+                                        position.bottom
+                                    )
                                 }
+                                iconHolderView.layoutParams = iconParams
                             }
-                        PromptSize.LARGE -> {
-                            left = 0
-                            top = 0
-                            right = view.width
-                            bottom = view.height
                         }
                     }
-
-                    // Round the panel outline
-                    panelView.outlineProvider =
-                        object : ViewOutlineProvider() {
-                            override fun getOutline(view: View, outline: Outline) {
-                                outline.setRoundRect(
-                                    left,
-                                    top,
-                                    right,
-                                    bottom,
-                                    cornerRadiusPx.toFloat()
-                                )
-                            }
+                    lifecycleScope.launch {
+                        viewModel.iconSize.collect { iconSize ->
+                            iconHolderView.layoutParams.width = iconSize.first
+                            iconHolderView.layoutParams.height = iconSize.second
+                            mediumConstraintSet.constrainWidth(R.id.biometric_icon, iconSize.first)
+                            mediumConstraintSet.constrainHeight(
+                                R.id.biometric_icon,
+                                iconSize.second
+                            )
                         }
-                }
-
-                view.repeatWhenAttached {
-                    var currentSize: PromptSize? = null
+                    }
 
                     lifecycleScope.launch {
                         viewModel.guidelineBounds.collect { bounds ->
@@ -249,87 +366,77 @@
                     lifecycleScope.launch {
                         combine(viewModel.position, viewModel.size, ::Pair).collect {
                             (position, size) ->
-                            view.doOnAttach {
-                                setVisibilities(size)
+                            setVisibilities(size)
 
-                                if (position.isLeft) {
-                                    if (size.isSmall) {
-                                        flipConstraintSet.clone(smallConstraintSet)
-                                    } else {
-                                        flipConstraintSet.clone(mediumConstraintSet)
-                                    }
-
-                                    // Move all content to other panel
-                                    flipConstraintSet.connect(
-                                        R.id.scrollView,
-                                        ConstraintSet.START,
-                                        R.id.midGuideline,
-                                        ConstraintSet.START
-                                    )
-                                    flipConstraintSet.connect(
-                                        R.id.scrollView,
-                                        ConstraintSet.END,
-                                        R.id.rightGuideline,
-                                        ConstraintSet.END
-                                    )
+                            if (position.isLeft) {
+                                if (size.isSmall) {
+                                    flipConstraintSet.clone(smallConstraintSet)
+                                } else {
+                                    flipConstraintSet.clone(mediumConstraintSet)
                                 }
 
-                                roundCorners(size, position)
-
-                                when {
-                                    size.isSmall -> {
-                                        if (position.isLeft) {
-                                            flipConstraintSet.applyTo(view)
-                                        } else {
-                                            smallConstraintSet.applyTo(view)
-                                        }
-                                    }
-                                    size.isMedium && currentSize.isSmall -> {
-                                        val autoTransition = AutoTransition()
-                                        autoTransition.setDuration(
-                                            ANIMATE_SMALL_TO_MEDIUM_DURATION_MS.toLong()
-                                        )
-
-                                        TransitionManager.beginDelayedTransition(
-                                            view,
-                                            autoTransition
-                                        )
-
-                                        if (position.isLeft) {
-                                            flipConstraintSet.applyTo(view)
-                                        } else {
-                                            mediumConstraintSet.applyTo(view)
-                                        }
-                                    }
-                                    size.isMedium -> {
-                                        if (position.isLeft) {
-                                            flipConstraintSet.applyTo(view)
-                                        } else {
-                                            mediumConstraintSet.applyTo(view)
-                                        }
-                                    }
-                                    size.isLarge -> {
-                                        val autoTransition = AutoTransition()
-                                        autoTransition.setDuration(
-                                            ANIMATE_MEDIUM_TO_LARGE_DURATION_MS.toLong()
-                                        )
-
-                                        TransitionManager.beginDelayedTransition(
-                                            view,
-                                            autoTransition
-                                        )
-                                        largeConstraintSet.applyTo(view)
-                                    }
-                                }
-
-                                currentSize = size
-                                view.visibility = View.VISIBLE
-                                viewModel.setIsIconViewLoaded(false)
-                                notifyAccessibilityChanged()
-
-                                view.invalidate()
-                                view.requestLayout()
+                                // Move all content to other panel
+                                flipConstraintSet.connect(
+                                    R.id.scrollView,
+                                    ConstraintSet.START,
+                                    R.id.midGuideline,
+                                    ConstraintSet.START
+                                )
+                                flipConstraintSet.connect(
+                                    R.id.scrollView,
+                                    ConstraintSet.END,
+                                    R.id.rightGuideline,
+                                    ConstraintSet.END
+                                )
                             }
+
+                            when {
+                                size.isSmall -> {
+                                    if (position.isLeft) {
+                                        flipConstraintSet.applyTo(view)
+                                    } else {
+                                        smallConstraintSet.applyTo(view)
+                                    }
+                                }
+                                size.isMedium && currentSize.isSmall -> {
+                                    val autoTransition = AutoTransition()
+                                    autoTransition.setDuration(
+                                        ANIMATE_SMALL_TO_MEDIUM_DURATION_MS.toLong()
+                                    )
+
+                                    TransitionManager.beginDelayedTransition(view, autoTransition)
+
+                                    if (position.isLeft) {
+                                        flipConstraintSet.applyTo(view)
+                                    } else {
+                                        mediumConstraintSet.applyTo(view)
+                                    }
+                                }
+                                size.isMedium -> {
+                                    if (position.isLeft) {
+                                        flipConstraintSet.applyTo(view)
+                                    } else {
+                                        mediumConstraintSet.applyTo(view)
+                                    }
+                                }
+                                size.isLarge && currentSize.isMedium -> {
+                                    val autoTransition = AutoTransition()
+                                    autoTransition.setDuration(
+                                        ANIMATE_MEDIUM_TO_LARGE_DURATION_MS.toLong()
+                                    )
+
+                                    TransitionManager.beginDelayedTransition(view, autoTransition)
+                                    largeConstraintSet.applyTo(view)
+                                }
+                            }
+
+                            currentSize = size
+                            currentPosition = position
+                            notifyAccessibilityChanged()
+
+                            panelView.invalidateOutline()
+                            view.invalidate()
+                            view.requestLayout()
                         }
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
index d9d3715..9e836c3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/PromptIconViewBinder.kt
@@ -17,12 +17,9 @@
 
 package com.android.systemui.biometrics.ui.binder
 
-import android.graphics.Rect
 import android.graphics.drawable.Animatable2
 import android.graphics.drawable.AnimatedVectorDrawable
 import android.graphics.drawable.Drawable
-import androidx.constraintlayout.widget.ConstraintLayout
-import androidx.constraintlayout.widget.ConstraintSet
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.airbnb.lottie.LottieAnimationView
@@ -77,83 +74,60 @@
                         }
                     }
 
-                launch {
-                    var lottieOnCompositionLoadedListener: LottieOnCompositionLoadedListener? = null
+                if (!constraintBp()) {
+                    launch {
+                        var lottieOnCompositionLoadedListener: LottieOnCompositionLoadedListener? =
+                            null
 
-                    combine(viewModel.activeAuthType, viewModel.iconSize, ::Pair).collect {
-                        (activeAuthType, iconSize) ->
-                        // Every time after bp shows, [isIconViewLoaded] is set to false in
-                        // [BiometricViewSizeBinder]. Then when biometric prompt view is redrew
-                        // (when size or activeAuthType changes), we need to update
-                        // [isIconViewLoaded] here to keep it correct.
-                        when (activeAuthType) {
-                            AuthType.Fingerprint,
-                            AuthType.Coex -> {
-                                /**
-                                 * View is only set visible in BiometricViewSizeBinder once
-                                 * PromptSize is determined that accounts for iconView size, to
-                                 * prevent prompt resizing being visible to the user.
-                                 *
-                                 * TODO(b/288175072): May be able to remove this once constraint
-                                 *   layout is implemented
-                                 */
-                                if (lottieOnCompositionLoadedListener != null) {
-                                    iconView.removeLottieOnCompositionLoadedListener(
+                        combine(viewModel.activeAuthType, viewModel.iconSize, ::Pair).collect {
+                            (activeAuthType, iconSize) ->
+                            // Every time after bp shows, [isIconViewLoaded] is set to false in
+                            // [BiometricViewSizeBinder]. Then when biometric prompt view is redrew
+                            // (when size or activeAuthType changes), we need to update
+                            // [isIconViewLoaded] here to keep it correct.
+                            when (activeAuthType) {
+                                AuthType.Fingerprint,
+                                AuthType.Coex -> {
+                                    /**
+                                     * View is only set visible in BiometricViewSizeBinder once
+                                     * PromptSize is determined that accounts for iconView size, to
+                                     * prevent prompt resizing being visible to the user.
+                                     *
+                                     * TODO(b/288175072): May be able to remove this once constraint
+                                     *   layout is implemented
+                                     */
+                                    if (lottieOnCompositionLoadedListener != null) {
+                                        iconView.removeLottieOnCompositionLoadedListener(
+                                            lottieOnCompositionLoadedListener!!
+                                        )
+                                    }
+                                    lottieOnCompositionLoadedListener =
+                                        LottieOnCompositionLoadedListener {
+                                            promptViewModel.setIsIconViewLoaded(true)
+                                        }
+                                    iconView.addLottieOnCompositionLoadedListener(
                                         lottieOnCompositionLoadedListener!!
                                     )
                                 }
-                                lottieOnCompositionLoadedListener =
-                                    LottieOnCompositionLoadedListener {
-                                        promptViewModel.setIsIconViewLoaded(true)
-                                    }
-                                iconView.addLottieOnCompositionLoadedListener(
-                                    lottieOnCompositionLoadedListener!!
-                                )
+                                AuthType.Face -> {
+                                    /**
+                                     * Set to true by default since face icon is a drawable, which
+                                     * doesn't have a LottieOnCompositionLoadedListener equivalent.
+                                     *
+                                     * TODO(b/318569643): To be updated once face assets are updated
+                                     *   from drawables
+                                     */
+                                    promptViewModel.setIsIconViewLoaded(true)
+                                }
                             }
-                            AuthType.Face -> {
-                                /**
-                                 * Set to true by default since face icon is a drawable, which
-                                 * doesn't have a LottieOnCompositionLoadedListener equivalent.
-                                 *
-                                 * TODO(b/318569643): To be updated once face assets are updated
-                                 *   from drawables
-                                 */
-                                promptViewModel.setIsIconViewLoaded(true)
-                            }
-                        }
 
-                        if (iconViewLayoutParamSizeOverride == null) {
-                            iconView.layoutParams.width = iconSize.first
-                            iconView.layoutParams.height = iconSize.second
+                            if (iconViewLayoutParamSizeOverride == null) {
+                                iconView.layoutParams.width = iconSize.first
+                                iconView.layoutParams.height = iconSize.second
 
-                            iconOverlayView.layoutParams.width = iconSize.first
-                            iconOverlayView.layoutParams.height = iconSize.second
-                        }
-                    }
-                }
-
-                launch {
-                    viewModel.iconPosition.collect { position ->
-                        if (constraintBp() && position != Rect()) {
-                            val iconParams = iconView.layoutParams as ConstraintLayout.LayoutParams
-
-                            if (position.left != 0) {
-                                iconParams.endToEnd = ConstraintSet.UNSET
-                                iconParams.leftMargin = position.left
+                                iconOverlayView.layoutParams.width = iconSize.first
+                                iconOverlayView.layoutParams.height = iconSize.second
                             }
-                            if (position.top != 0) {
-                                iconParams.bottomToBottom = ConstraintSet.UNSET
-                                iconParams.topMargin = position.top
-                            }
-                            if (position.right != 0) {
-                                iconParams.startToStart = ConstraintSet.UNSET
-                                iconParams.rightMargin = position.right
-                            }
-                            if (position.bottom != 0) {
-                                iconParams.topToTop = ConstraintSet.UNSET
-                                iconParams.bottomMargin = position.bottom
-                            }
-                            iconView.layoutParams = iconParams
                         }
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
index 245817e..4bdbfa2 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
@@ -122,11 +122,9 @@
         val overlayViewModel =
             SideFpsOverlayViewModel(
                 applicationContext,
-                biometricStatusInteractor.get(),
                 deviceEntrySideFpsOverlayInteractor.get(),
                 displayStateInteractor.get(),
                 sfpsSensorInteractor.get(),
-                sideFpsProgressBarViewModel.get()
             )
         bind(overlayView!!, overlayViewModel, fpsUnlockTracker.get(), windowManager.get())
         overlayView!!.visibility = View.INVISIBLE
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
index 8dbed5f..bde3e99 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptIconViewModel.kt
@@ -66,10 +66,9 @@
      */
     val activeAuthType: Flow<AuthType> =
         combine(
-            promptViewModel.size,
             promptViewModel.modalities.distinctUntilChanged(),
             promptViewModel.faceMode.distinctUntilChanged()
-        ) { _, modalities, faceMode ->
+        ) { modalities, faceMode ->
             if (modalities.hasFaceAndFingerprint && !faceMode) {
                 AuthType.Coex
             } else if (modalities.hasFaceOnly || faceMode) {
@@ -103,68 +102,6 @@
             }
             .distinctUntilChanged()
 
-    val iconPosition: Flow<Rect> =
-        combine(
-                udfpsSensorBounds,
-                promptViewModel.size,
-                promptViewModel.position,
-                promptViewModel.modalities
-            ) { sensorBounds, size, position, modalities ->
-                when (position) {
-                    PromptPosition.Bottom ->
-                        if (size.isSmall) {
-                            Rect(0, 0, 0, promptViewModel.portraitSmallBottomPadding)
-                        } else if (size.isMedium && modalities.hasUdfps) {
-                            Rect(0, 0, 0, sensorBounds.bottom)
-                        } else if (size.isMedium) {
-                            Rect(0, 0, 0, promptViewModel.portraitMediumBottomPadding)
-                        } else {
-                            // Large screen
-                            Rect(0, 0, 0, promptViewModel.portraitLargeScreenBottomPadding)
-                        }
-                    PromptPosition.Right ->
-                        if (size.isSmall || modalities.hasFaceOnly) {
-                            Rect(
-                                0,
-                                0,
-                                promptViewModel.landscapeSmallHorizontalPadding,
-                                promptViewModel.landscapeSmallBottomPadding
-                            )
-                        } else if (size.isMedium && modalities.hasUdfps) {
-                            Rect(0, 0, sensorBounds.right, sensorBounds.bottom)
-                        } else {
-                            // SFPS
-                            Rect(
-                                0,
-                                0,
-                                promptViewModel.landscapeMediumHorizontalPadding,
-                                promptViewModel.landscapeMediumBottomPadding
-                            )
-                        }
-                    PromptPosition.Left ->
-                        if (size.isSmall || modalities.hasFaceOnly) {
-                            Rect(
-                                promptViewModel.landscapeSmallHorizontalPadding,
-                                0,
-                                0,
-                                promptViewModel.landscapeSmallBottomPadding
-                            )
-                        } else if (size.isMedium && modalities.hasUdfps) {
-                            Rect(sensorBounds.left, 0, 0, sensorBounds.bottom)
-                        } else {
-                            // SFPS
-                            Rect(
-                                promptViewModel.landscapeMediumHorizontalPadding,
-                                0,
-                                0,
-                                promptViewModel.landscapeMediumBottomPadding
-                            )
-                        }
-                    PromptPosition.Top -> Rect()
-                }
-            }
-            .distinctUntilChanged()
-
     /** Whether an error message is currently being shown. */
     val showingError = promptViewModel.showingError
 
@@ -215,8 +152,8 @@
         combine(
             promptViewModel.position,
             activeAuthType,
-            promptViewModel.fingerprintSensorWidth,
-            promptViewModel.fingerprintSensorHeight,
+            promptViewModel.legacyFingerprintSensorWidth,
+            promptViewModel.legacyFingerprintSensorHeight,
         ) { _, activeAuthType, fingerprintSensorWidth, fingerprintSensorHeight ->
             if (activeAuthType == AuthType.Face) {
                 Pair(promptViewModel.faceIconWidth, promptViewModel.faceIconHeight)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index 4e9acbd..2104f3e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -27,6 +27,7 @@
 import android.hardware.biometrics.Flags.customBiometricPrompt
 import android.hardware.biometrics.PromptContentView
 import android.util.Log
+import android.util.RotationUtils
 import android.view.HapticFeedbackConstants
 import android.view.MotionEvent
 import com.android.systemui.Flags.bpTalkback
@@ -120,7 +121,28 @@
             R.dimen.biometric_prompt_landscape_medium_horizontal_padding
         )
 
-    val fingerprintSensorWidth: Flow<Int> =
+    private val udfpsSensorBounds: Flow<Rect> =
+        combine(
+                udfpsOverlayInteractor.udfpsOverlayParams,
+                displayStateInteractor.currentRotation
+            ) { params, rotation ->
+                val rotatedBounds = Rect(params.sensorBounds)
+                RotationUtils.rotateBounds(
+                    rotatedBounds,
+                    params.naturalDisplayWidth,
+                    params.naturalDisplayHeight,
+                    rotation.ordinal
+                )
+                Rect(
+                    rotatedBounds.left,
+                    rotatedBounds.top,
+                    params.logicalDisplayWidth - rotatedBounds.right,
+                    params.logicalDisplayHeight - rotatedBounds.bottom
+                )
+            }
+            .distinctUntilChanged()
+
+    val legacyFingerprintSensorWidth: Flow<Int> =
         combine(modalities, udfpsOverlayInteractor.udfpsOverlayParams) { modalities, overlayParams
             ->
             if (modalities.hasUdfps) {
@@ -130,7 +152,7 @@
             }
         }
 
-    val fingerprintSensorHeight: Flow<Int> =
+    val legacyFingerprintSensorHeight: Flow<Int> =
         combine(modalities, udfpsOverlayInteractor.udfpsOverlayParams) { modalities, overlayParams
             ->
             if (modalities.hasUdfps) {
@@ -140,6 +162,12 @@
             }
         }
 
+    val fingerprintSensorWidth: Int =
+        udfpsOverlayInteractor.udfpsOverlayParams.value.sensorBounds.width()
+
+    val fingerprintSensorHeight: Int =
+        udfpsOverlayInteractor.udfpsOverlayParams.value.sensorBounds.height()
+
     private val _accessibilityHint = MutableSharedFlow<String>()
 
     /** Hint for talkback directional guidance */
@@ -276,40 +304,54 @@
             R.dimen.biometric_prompt_medium_mid_guideline_padding
         )
 
-    /**
-     * Rect for positioning prompt guidelines (left, top, right, mid)
-     *
-     * Negative values are used to signify that guideline measuring should be flipped, measuring
-     * from opposite side of the screen
-     */
-    val guidelineBounds: Flow<Rect> =
-        combine(size, position, modalities) { size, position, modalities ->
-                if (position.isBottom) {
-                    Rect(0, 0, 0, 0)
-                } else if (position.isRight) {
-                    if (size.isSmall) {
-                        Rect(-smallHorizontalGuidelinePadding, 0, 0, 0)
-                    } else if (modalities.hasUdfps) {
-                        Rect(udfpsHorizontalGuidelinePadding, 0, 0, udfpsMidGuidelinePadding)
-                    } else if (modalities.isEmpty) {
-                        // TODO: Temporary fix until no biometric landscape layout is added
-                        Rect(-mediumHorizontalGuidelinePadding, 0, 0, 6)
-                    } else {
-                        Rect(-mediumHorizontalGuidelinePadding, 0, 0, mediumMidGuidelinePadding)
-                    }
-                } else if (position.isLeft) {
-                    if (size.isSmall) {
-                        Rect(0, 0, -smallHorizontalGuidelinePadding, 0)
-                    } else if (modalities.hasUdfps) {
-                        Rect(0, 0, udfpsHorizontalGuidelinePadding, -udfpsMidGuidelinePadding)
-                    } else if (modalities.isEmpty) {
-                        // TODO: Temporary fix until no biometric landscape layout is added
-                        Rect(0, 0, -mediumHorizontalGuidelinePadding, -6)
-                    } else {
-                        Rect(0, 0, -mediumHorizontalGuidelinePadding, -mediumMidGuidelinePadding)
-                    }
-                } else {
-                    Rect()
+    /** Rect for positioning biometric icon */
+    val iconPosition: Flow<Rect> =
+        combine(udfpsSensorBounds, size, position, modalities) {
+                sensorBounds,
+                size,
+                position,
+                modalities ->
+                when (position) {
+                    PromptPosition.Bottom ->
+                        if (size.isSmall) {
+                            Rect(0, 0, 0, portraitSmallBottomPadding)
+                        } else if (size.isMedium && modalities.hasUdfps) {
+                            Rect(0, 0, 0, sensorBounds.bottom)
+                        } else if (size.isMedium) {
+                            Rect(0, 0, 0, portraitMediumBottomPadding)
+                        } else {
+                            // Large screen
+                            Rect(0, 0, 0, portraitLargeScreenBottomPadding)
+                        }
+                    PromptPosition.Right ->
+                        if (size.isSmall || modalities.hasFaceOnly) {
+                            Rect(0, 0, landscapeSmallHorizontalPadding, landscapeSmallBottomPadding)
+                        } else if (size.isMedium && modalities.hasUdfps) {
+                            Rect(0, 0, sensorBounds.right, sensorBounds.bottom)
+                        } else {
+                            // SFPS
+                            Rect(
+                                0,
+                                0,
+                                landscapeMediumHorizontalPadding,
+                                landscapeMediumBottomPadding
+                            )
+                        }
+                    PromptPosition.Left ->
+                        if (size.isSmall || modalities.hasFaceOnly) {
+                            Rect(landscapeSmallHorizontalPadding, 0, 0, landscapeSmallBottomPadding)
+                        } else if (size.isMedium && modalities.hasUdfps) {
+                            Rect(sensorBounds.left, 0, 0, sensorBounds.bottom)
+                        } else {
+                            // SFPS
+                            Rect(
+                                landscapeMediumHorizontalPadding,
+                                0,
+                                0,
+                                landscapeMediumBottomPadding
+                            )
+                        }
+                    PromptPosition.Top -> Rect()
                 }
             }
             .distinctUntilChanged()
@@ -373,6 +415,62 @@
         _isIconViewLoaded.value = iconViewLoaded
     }
 
+    /** The size of the biometric icon */
+    val iconSize: Flow<Pair<Int, Int>> =
+        combine(iconViewModel.activeAuthType, modalities) { activeAuthType, modalities ->
+            if (activeAuthType == PromptIconViewModel.AuthType.Face) {
+                Pair(faceIconWidth, faceIconHeight)
+            } else {
+                if (modalities.hasUdfps) {
+                    Pair(fingerprintSensorWidth, fingerprintSensorHeight)
+                } else {
+                    Pair(fingerprintIconWidth, fingerprintIconHeight)
+                }
+            }
+        }
+
+    /**
+     * Rect for positioning prompt guidelines (left, top, right, mid)
+     *
+     * Negative values are used to signify that guideline measuring should be flipped, measuring
+     * from opposite side of the screen
+     */
+    val guidelineBounds: Flow<Rect> =
+        combine(iconPosition, size, position, modalities) { _, size, position, modalities ->
+                when (position) {
+                    PromptPosition.Bottom -> Rect(0, 0, 0, 0)
+                    PromptPosition.Right ->
+                        if (size.isSmall) {
+                            Rect(-smallHorizontalGuidelinePadding, 0, 0, 0)
+                        } else if (modalities.hasUdfps) {
+                            Rect(udfpsHorizontalGuidelinePadding, 0, 0, udfpsMidGuidelinePadding)
+                        } else if (modalities.isEmpty) {
+                            // TODO: Temporary fix until no biometric landscape layout is added
+                            Rect(-mediumHorizontalGuidelinePadding, 0, 0, 6)
+                        } else {
+                            Rect(-mediumHorizontalGuidelinePadding, 0, 0, mediumMidGuidelinePadding)
+                        }
+                    PromptPosition.Left ->
+                        if (size.isSmall) {
+                            Rect(0, 0, -smallHorizontalGuidelinePadding, 0)
+                        } else if (modalities.hasUdfps) {
+                            Rect(0, 0, udfpsHorizontalGuidelinePadding, -udfpsMidGuidelinePadding)
+                        } else if (modalities.isEmpty) {
+                            // TODO: Temporary fix until no biometric landscape layout is added
+                            Rect(0, 0, -mediumHorizontalGuidelinePadding, -6)
+                        } else {
+                            Rect(
+                                0,
+                                0,
+                                -mediumHorizontalGuidelinePadding,
+                                -mediumMidGuidelinePadding
+                            )
+                        }
+                    PromptPosition.Top -> Rect()
+                }
+            }
+            .distinctUntilChanged()
+
     /** Padding for prompt UI elements */
     val promptPadding: Flow<Rect> =
         combine(size, displayStateInteractor.currentRotation) { size, rotation ->
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
index 412d0c3..19ea007 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModel.kt
@@ -30,7 +30,6 @@
 import com.airbnb.lottie.model.KeyPath
 import com.android.systemui.Flags.constraintBp
 import com.android.systemui.biometrics.Utils
-import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
 import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
 import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
 import com.android.systemui.biometrics.domain.model.SideFpsSensorLocation
@@ -38,7 +37,6 @@
 import com.android.systemui.biometrics.shared.model.LottieCallback
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
-import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
 import com.android.systemui.res.R
 import com.android.systemui.util.kotlin.sample
 import javax.inject.Inject
@@ -54,11 +52,9 @@
 @Inject
 constructor(
     @Application private val applicationContext: Context,
-    biometricStatusInteractor: BiometricStatusInteractor,
     deviceEntrySideFpsOverlayInteractor: DeviceEntrySideFpsOverlayInteractor,
     displayStateInteractor: DisplayStateInteractor,
     sfpsSensorInteractor: SideFpsSensorInteractor,
-    sideFpsProgressBarViewModel: SideFpsProgressBarViewModel
 ) {
     /** Contains properties of the side fingerprint sensor indicator */
     data class OverlayViewProperties(
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index cb458ef..45e39ca 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -34,7 +34,7 @@
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
 import com.android.systemui.log.SessionTracker
 import com.android.systemui.power.domain.interactor.PowerInteractor
-import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.domain.interactor.SceneBackInteractor
 import com.android.systemui.scene.shared.model.Scenes
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -59,7 +59,7 @@
     private val powerInteractor: PowerInteractor,
     private val uiEventLogger: UiEventLogger,
     private val sessionTracker: SessionTracker,
-    sceneInteractor: SceneInteractor,
+    sceneBackInteractor: SceneBackInteractor,
 ) {
     private val _onIncorrectBouncerInput = MutableSharedFlow<Unit>()
     val onIncorrectBouncerInput: SharedFlow<Unit> = _onIncorrectBouncerInput
@@ -95,7 +95,9 @@
 
     /** The scene to show when bouncer is dismissed. */
     val dismissDestination: Flow<SceneKey> =
-        sceneInteractor.previousScene(Scenes.Bouncer).map { it ?: Scenes.Lockscreen }
+        sceneBackInteractor.backScene
+            .filter { it != Scenes.Bouncer }
+            .map { it ?: Scenes.Lockscreen }
 
     /** Notifies that the user has places down a pointer, not necessarily dragging just yet. */
     fun onDown() {
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
index 0123857..82fe2f1 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java
@@ -33,7 +33,6 @@
 
 import javax.inject.Inject;
 
-
 /**
  * False touch if proximity sensor is covered for more than a certain percentage of the gesture.
  *
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index bfc80a7..bd0e729 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -18,7 +18,6 @@
 
 import static android.content.Intent.ACTION_CLOSE_SYSTEM_DIALOGS;
 
-
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_SHOW_ACTIONS;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_SHOWN;
 import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_TAPPED;
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
index 0fd34bd..ff9fba4 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java
@@ -25,18 +25,18 @@
 import android.view.Display;
 import android.view.LayoutInflater;
 
-import com.android.systemui.res.R;
 import com.android.systemui.clipboardoverlay.ClipboardOverlayView;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.DisplayTracker;
 
+import dagger.Module;
+import dagger.Provides;
+
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 
 import javax.inject.Qualifier;
 
-import dagger.Module;
-import dagger.Provides;
-
 /** Module for {@link com.android.systemui.clipboardoverlay}. */
 @Module
 public interface ClipboardOverlayModule {
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
index 638af58..e0e1971 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractor.kt
@@ -48,6 +48,12 @@
             }
         }
 
+    /** Returns the unadjusted screen size. */
+    val maxBounds: Flow<Rect> =
+        repository.configurationValues
+            .map { Rect(it.windowConfiguration.maxBounds) }
+            .distinctUntilChanged()
+
     /**
      * Returns screen size adjusted to rotation, so returned screen sizes are stable across all
      * rotations, could be useful if you need to react to screen resize (e.g. fold/unfold on
diff --git a/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt b/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
index 7fa091a..2406cc6 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
@@ -76,7 +76,12 @@
             val config =
                 SceneContainerConfig(
                     sceneKeys = listOf(CommunalScenes.Blank, CommunalScenes.Communal),
-                    initialSceneKey = CommunalScenes.Blank
+                    initialSceneKey = CommunalScenes.Blank,
+                    navigationDistances =
+                        mapOf(
+                            CommunalScenes.Blank to 0,
+                            CommunalScenes.Communal to 1,
+                        ),
                 )
             return SceneDataSourceDelegator(applicationScope, config)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
index 4ac43bc..511bdc4 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
@@ -88,14 +88,14 @@
     /** Whether in edit mode for the communal hub. */
     open val isEditMode = false
 
-    /** Whether the popup message triggered by dismissing the CTA tile is showing. */
-    open val isPopupOnDismissCtaShowing: Flow<Boolean> = flowOf(false)
+    /** Whether the type of popup currently showing */
+    open val currentPopup: Flow<PopupType?> = flowOf(null)
 
     /** Whether the communal hub is empty with no widget available. */
     open val isEmptyState: Flow<Boolean> = flowOf(false)
 
-    /** Hide the popup message triggered by dismissing the CTA tile. */
-    open fun onHidePopupAfterDismissCta() {}
+    /** Called as the UI request to dismiss the any displaying popup */
+    open fun onHidePopup() {}
 
     /** Called as the UI requests deleting a widget. */
     open fun onDeleteWidget(id: Int) {}
@@ -127,6 +127,9 @@
     /** Called as the user cancels dragging a widget to reorder. */
     open fun onReorderWidgetCancel() {}
 
+    /** Called as the user request to show the customize widget button. */
+    open fun onShowCustomizeWidgetButton() {}
+
     /** Set the key of the currently selected item */
     fun setSelectedKey(key: String?) {
         _selectedKey.value = key
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index f13b5759..9dacf8c 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -90,9 +90,8 @@
             .distinctUntilChanged()
             .onEach { logger.d("isEmptyState: $it") }
 
-    private val _isPopupOnDismissCtaShowing: MutableStateFlow<Boolean> = MutableStateFlow(false)
-    override val isPopupOnDismissCtaShowing: Flow<Boolean> =
-        _isPopupOnDismissCtaShowing.asStateFlow()
+    private val _currentPopup: MutableStateFlow<PopupType?> = MutableStateFlow(null)
+    override val currentPopup: Flow<PopupType?> = _currentPopup.asStateFlow()
 
     private val _isEnableWidgetDialogShowing: MutableStateFlow<Boolean> = MutableStateFlow(false)
     val isEnableWidgetDialogShowing: Flow<Boolean> = _isEnableWidgetDialogShowing.asStateFlow()
@@ -124,14 +123,16 @@
     override fun onDismissCtaTile() {
         scope.launch {
             communalInteractor.dismissCtaTile()
-            setPopupOnDismissCtaVisibility(true)
-            schedulePopupHiding()
+            setCurrentPopupType(PopupType.CtaTile)
         }
     }
 
-    override fun onHidePopupAfterDismissCta() {
-        cancelDelayedPopupHiding()
-        setPopupOnDismissCtaVisibility(false)
+    override fun onShowCustomizeWidgetButton() {
+        setCurrentPopupType(PopupType.CustomizeWidgetButton)
+    }
+
+    override fun onHidePopup() {
+        setCurrentPopupType(null)
     }
 
     override fun onOpenEnableWidgetDialog() {
@@ -168,25 +169,22 @@
         _isEnableWorkProfileDialogShowing.value = isVisible
     }
 
-    private fun setPopupOnDismissCtaVisibility(isVisible: Boolean) {
-        _isPopupOnDismissCtaShowing.value = isVisible
+    private fun setCurrentPopupType(popupType: PopupType?) {
+        _currentPopup.value = popupType
+        delayedHideCurrentPopupJob?.cancel()
+
+        if (popupType != null) {
+            delayedHideCurrentPopupJob =
+                scope.launch {
+                    delay(POPUP_AUTO_HIDE_TIMEOUT_MS)
+                    setCurrentPopupType(null)
+                }
+        } else {
+            delayedHideCurrentPopupJob = null
+        }
     }
 
-    private var delayedHidePopupJob: Job? = null
-
-    private fun schedulePopupHiding() {
-        cancelDelayedPopupHiding()
-        delayedHidePopupJob =
-            scope.launch {
-                delay(POPUP_AUTO_HIDE_TIMEOUT_MS)
-                onHidePopupAfterDismissCta()
-            }
-    }
-
-    private fun cancelDelayedPopupHiding() {
-        delayedHidePopupJob?.cancel()
-        delayedHidePopupJob = null
-    }
+    private var delayedHideCurrentPopupJob: Job? = null
 
     /** Whether we can transition to a new scene based on a user gesture. */
     fun canChangeScene(): Boolean {
@@ -197,3 +195,8 @@
         const val POPUP_AUTO_HIDE_TIMEOUT_MS = 12000L
     }
 }
+
+sealed class PopupType {
+    object CtaTile : PopupType()
+    object CustomizeWidgetButton : PopupType()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/complication/ComplicationLayoutEngine.java b/packages/SystemUI/src/com/android/systemui/complication/ComplicationLayoutEngine.java
index f7b6b0f..15ec4d4 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/ComplicationLayoutEngine.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/ComplicationLayoutEngine.java
@@ -40,10 +40,10 @@
 import androidx.constraintlayout.widget.ConstraintLayout;
 import androidx.constraintlayout.widget.Constraints;
 
-import com.android.systemui.res.R;
 import com.android.systemui.complication.ComplicationLayoutParams.Direction;
 import com.android.systemui.complication.ComplicationLayoutParams.Position;
 import com.android.systemui.complication.dagger.ComplicationModule;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.touch.TouchInsetManager;
 
diff --git a/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationHostViewModule.java b/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationHostViewModule.java
index 712213a..9dd48ea 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationHostViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationHostViewModule.java
@@ -22,8 +22,8 @@
 import androidx.constraintlayout.widget.ConstraintLayout;
 
 import com.android.internal.util.Preconditions;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationModule.java b/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationModule.java
index 57841af..9475372 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationModule.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationModule.java
@@ -34,6 +34,7 @@
 
 import javax.inject.Named;
 import javax.inject.Scope;
+
 /**
  * Module for housing components related to rendering complications.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamHomeControlsComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamHomeControlsComplicationComponent.java
index b6dcfcb..63ac77d 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamHomeControlsComplicationComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamHomeControlsComplicationComponent.java
@@ -34,7 +34,6 @@
 import dagger.Provides;
 import dagger.Subcomponent;
 
-
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 
diff --git a/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamMediaEntryComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamMediaEntryComplicationComponent.java
index c0a292c..b680393 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamMediaEntryComplicationComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamMediaEntryComplicationComponent.java
@@ -21,8 +21,8 @@
 import android.view.LayoutInflater;
 import android.view.View;
 
-import com.android.systemui.res.R;
 import com.android.systemui.complication.DreamMediaEntryComplication;
+import com.android.systemui.res.R;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/packages/SystemUI/src/com/android/systemui/complication/dagger/RegisteredComplicationsModule.java b/packages/SystemUI/src/com/android/systemui/complication/dagger/RegisteredComplicationsModule.java
index 92fdb1e..6f1b098 100644
--- a/packages/SystemUI/src/com/android/systemui/complication/dagger/RegisteredComplicationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/complication/dagger/RegisteredComplicationsModule.java
@@ -19,12 +19,12 @@
 import android.content.res.Resources;
 import android.view.ViewGroup;
 
-import com.android.systemui.res.R;
 import com.android.systemui.complication.ComplicationLayoutParams;
 import com.android.systemui.dagger.SystemUIBinder;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
+import com.android.systemui.res.R;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
index 2af49aa..db7ffc1 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
@@ -20,8 +20,6 @@
 import android.content.pm.PackageManager
 import com.android.systemui.controls.ControlsMetricsLogger
 import com.android.systemui.controls.ControlsMetricsLoggerImpl
-import com.android.systemui.controls.settings.ControlsSettingsRepository
-import com.android.systemui.controls.settings.ControlsSettingsRepositoryImpl
 import com.android.systemui.controls.controller.ControlsBindingController
 import com.android.systemui.controls.controller.ControlsBindingControllerImpl
 import com.android.systemui.controls.controller.ControlsController
@@ -40,14 +38,20 @@
 import com.android.systemui.controls.panels.SelectedComponentRepositoryImpl
 import com.android.systemui.controls.settings.ControlsSettingsDialogManager
 import com.android.systemui.controls.settings.ControlsSettingsDialogManagerImpl
+import com.android.systemui.controls.settings.ControlsSettingsRepository
+import com.android.systemui.controls.settings.ControlsSettingsRepositoryImpl
 import com.android.systemui.controls.ui.ControlActionCoordinator
 import com.android.systemui.controls.ui.ControlActionCoordinatorImpl
 import com.android.systemui.controls.ui.ControlsActivity
 import com.android.systemui.controls.ui.ControlsUiController
 import com.android.systemui.controls.ui.ControlsUiControllerImpl
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.qs.QsEventLogger
+import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.qs.tiles.DeviceControlsTile
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
 import dagger.Binds
 import dagger.BindsOptionalOf
 import dagger.Module
@@ -75,6 +79,22 @@
         fun providesControlsFeatureEnabled(pm: PackageManager): Boolean {
             return pm.hasSystemFeature(PackageManager.FEATURE_CONTROLS)
         }
+
+        const val DEVICE_CONTROLS_SPEC = "controls"
+
+        @Provides
+        @IntoMap
+        @StringKey(DEVICE_CONTROLS_SPEC)
+        fun provideDeviceControlsTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+                QSTileConfig(
+                        tileSpec = TileSpec.create(DEVICE_CONTROLS_SPEC),
+                        uiConfig =
+                        QSTileUIConfig.Resource(
+                                iconRes = com.android.systemui.res.R.drawable.controls_icon,
+                                labelRes = com.android.systemui.res.R.string.quick_controls_title
+                        ),
+                        instanceId = uiEventLogger.getNewInstanceId(),
+                )
     }
 
     @Binds
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/NightDisplayListenerModule.java b/packages/SystemUI/src/com/android/systemui/dagger/NightDisplayListenerModule.java
index 7091105..42fca7d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/NightDisplayListenerModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/NightDisplayListenerModule.java
@@ -23,11 +23,11 @@
 
 import com.android.systemui.dagger.qualifiers.Background;
 
-import javax.inject.Inject;
-
 import dagger.Module;
 import dagger.Provides;
 
+import javax.inject.Inject;
+
 /**
  * Module for providing a {@link NightDisplayListener}.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceGlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceGlobalRootComponent.java
index be93c9f..c663db0 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceGlobalRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceGlobalRootComponent.java
@@ -16,10 +16,10 @@
 
 package com.android.systemui.dagger;
 
-import javax.inject.Singleton;
-
 import dagger.Component;
 
+import javax.inject.Singleton;
+
 /**
  * Root component for Dagger injection used in AOSP.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/InstrumentationTest.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/InstrumentationTest.java
index a803a39..9430445 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/InstrumentationTest.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/InstrumentationTest.java
@@ -23,7 +23,6 @@
 
 import javax.inject.Qualifier;
 
-
 /**
  * An annotation for injecting whether or not we are running in a test environment.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/TestHarness.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/TestHarness.java
index f68ab18..35c7b76 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/TestHarness.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/TestHarness.java
@@ -23,7 +23,6 @@
 
 import javax.inject.Qualifier;
 
-
 /**
  * An annotation for injecting whether or not we are running in a test environment.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
index e418641..f1ab4d1 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -250,7 +250,10 @@
             listOf(
                     *gatingConditionsForAuthAndDetect(),
                     Pair(isLockedOut.isFalse(), "isNotInLockOutState"),
-                    Pair(trustRepository.isCurrentUserTrusted.isFalse(), "currentUserIsNotTrusted"),
+                    Pair(
+                        keyguardRepository.isKeyguardDismissible.isFalse(),
+                        "keyguardIsNotDismissible"
+                    ),
                     Pair(
                         biometricSettingsRepository.isFaceAuthCurrentlyAllowed,
                         "isFaceAuthCurrentlyAllowed"
@@ -273,7 +276,7 @@
                     Pair(
                         biometricSettingsRepository.isFaceAuthCurrentlyAllowed
                             .isFalse()
-                            .or(trustRepository.isCurrentUserTrusted),
+                            .or(keyguardRepository.isKeyguardDismissible),
                         "faceAuthIsNotCurrentlyAllowedOrCurrentUserIsTrusted"
                     ),
                     // We don't want to run face detect if fingerprint can be used to unlock the
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt
index 98deda09..ffe392a 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/FaceHelpMessageDeferralInteractor.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.deviceentry.domain.interactor
 
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_START
 import android.hardware.face.FaceManager
 import com.android.systemui.biometrics.FaceHelpMessageDeferralFactory
 import com.android.systemui.dagger.SysUISingleton
@@ -86,7 +87,7 @@
                     }
                 }
                 .collect {
-                    if (it.acquiredInfo == FaceManager.FACE_ACQUIRED_START) {
+                    if (it.acquiredInfo == FACE_ACQUIRED_START) {
                         faceHelpMessageDeferral.reset()
                     }
                     faceHelpMessageDeferral.processFrame(it.acquiredInfo)
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt
index 5f1667a..3365340 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/model/FaceAuthenticationModels.kt
@@ -16,6 +16,12 @@
 
 package com.android.systemui.deviceentry.shared.model
 
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_CANCELED
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_UNABLE_TO_PROCESS
 import android.hardware.face.FaceManager
 import android.os.SystemClock.elapsedRealtime
 
@@ -62,24 +68,22 @@
      * Method that checks if [msgId] is a lockout error. A lockout error means that face
      * authentication is locked out.
      */
-    fun isLockoutError() =
-        msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT || msgId == FaceManager.FACE_ERROR_LOCKOUT
+    fun isLockoutError() = msgId == FACE_ERROR_LOCKOUT_PERMANENT || msgId == FACE_ERROR_LOCKOUT
 
     /**
      * Method that checks if [msgId] is a cancellation error. This means that face authentication
      * was cancelled before it completed.
      */
-    fun isCancellationError() = msgId == FaceManager.FACE_ERROR_CANCELED
+    fun isCancellationError() = msgId == FACE_ERROR_CANCELED
 
-    fun isUnableToProcessError() = msgId == FaceManager.FACE_ERROR_UNABLE_TO_PROCESS
+    fun isUnableToProcessError() = msgId == FACE_ERROR_UNABLE_TO_PROCESS
 
     /** Method that checks if [msgId] is a hardware error. */
     fun isHardwareError() =
-        msgId == FaceManager.FACE_ERROR_HW_UNAVAILABLE ||
-            msgId == FaceManager.FACE_ERROR_UNABLE_TO_PROCESS
+        msgId == FACE_ERROR_HW_UNAVAILABLE || msgId == FACE_ERROR_UNABLE_TO_PROCESS
 
     /** Method that checks if [msgId] is a timeout error. */
-    fun isTimeoutError() = msgId == FaceManager.FACE_ERROR_TIMEOUT
+    fun isTimeoutError() = msgId == FACE_ERROR_TIMEOUT
 
     companion object {
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
index 8e542b5..e182d0b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java
@@ -28,8 +28,8 @@
 import android.util.KeyValueListParser;
 import android.util.Log;
 
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.res.R;
 
 import javax.inject.Inject;
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java
index de0bdd3..2cafe99 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSuppressor.java
@@ -26,12 +26,12 @@
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
 
+import dagger.Lazy;
+
 import java.io.PrintWriter;
 
 import javax.inject.Inject;
 
-import dagger.Lazy;
-
 /**
  * Handles suppressing doze on:
  * 1. INITIALIZED, don't allow dozing at all when:
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index 0c2709e..8c0a73c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -48,13 +48,13 @@
 import com.android.systemui.statusbar.BlurUtils;
 import com.android.systemui.util.ViewController;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+
 import java.util.Arrays;
 
 import javax.inject.Inject;
 import javax.inject.Named;
 
-import kotlinx.coroutines.CoroutineDispatcher;
-
 /**
  * View controller for {@link DreamOverlayContainerView}.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index a9ef531..aa7a7da 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 android.service.dreams.Flags.dreamWakeRedirect;
+
 import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_WINDOW_TITLE;
 import static com.android.systemui.dreams.dagger.DreamModule.DREAM_TOUCH_INSET_MANAGER;
 import static com.android.systemui.dreams.dagger.DreamModule.HOME_CONTROL_PANEL_DREAM_COMPONENT;
@@ -149,6 +151,14 @@
 
     private final CommunalInteractor mCommunalInteractor;
 
+    private boolean mCommunalAvailable;
+
+    final Consumer<Boolean> mIsCommunalAvailableCallback =
+            isAvailable -> {
+                mCommunalAvailable = isAvailable;
+                updateRedirectWakeup();
+            };
+
     private final SystemDialogsCloser mSystemDialogsCloser;
 
     private final KeyguardUpdateMonitorCallback mKeyguardCallback =
@@ -287,6 +297,8 @@
 
         mExecutor.execute(() -> setLifecycleStateLocked(Lifecycle.State.CREATED));
 
+        collectFlow(getLifecycle(), mCommunalInteractor.isCommunalAvailable(),
+                mIsCommunalAvailableCallback);
         collectFlow(getLifecycle(), communalInteractor.isCommunalVisible(),
                 mCommunalVisibleConsumer);
         collectFlow(getLifecycle(), keyguardInteractor.primaryBouncerShowing,
@@ -359,7 +371,9 @@
             return;
         }
 
-        setLifecycleStateLocked(Lifecycle.State.RESUMED);
+        // Set lifecycle to resumed only if there's nothing covering the dream, ex. shade, bouncer,
+        // or hub. These updates can come in before onStartDream runs.
+        updateLifecycleStateLocked();
         mStateController.setOverlayActive(true);
         final ComponentName dreamComponent = getDreamComponent();
         mStateController.setLowLightActive(
@@ -372,6 +386,16 @@
 
         mDreamOverlayCallbackController.onStartDream();
         mStarted = true;
+
+        updateRedirectWakeup();
+    }
+
+    private void updateRedirectWakeup() {
+        if (!mStarted || !dreamWakeRedirect()) {
+            return;
+        }
+
+        redirectWake(mCommunalAvailable);
     }
 
     @Override
@@ -379,6 +403,11 @@
         resetCurrentDreamOverlayLocked();
     }
 
+    @Override
+    public void onWakeRequested() {
+        mCommunalInteractor.changeScene(CommunalScenes.Communal, null);
+    }
+
     private Lifecycle.State getLifecycleStateLocked() {
         return mLifecycleRegistry.getCurrentState();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java b/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
index 4dd97d5..d81949d 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
@@ -21,10 +21,10 @@
 import com.android.systemui.dagger.qualifiers.Application;
 import com.android.systemui.shared.condition.Condition;
 
-import javax.inject.Inject;
-
 import kotlinx.coroutines.CoroutineScope;
 
+import javax.inject.Inject;
+
 /**
  * {@link AssistantAttentionCondition} provides a signal when assistant has the user's attention.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java b/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
index 99688be..c7fe1e1 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
@@ -22,10 +22,10 @@
 import com.android.systemui.dagger.qualifiers.Application;
 import com.android.systemui.shared.condition.Condition;
 
-import javax.inject.Inject;
-
 import kotlinx.coroutines.CoroutineScope;
 
+import javax.inject.Inject;
+
 /**
  * {@link DreamCondition} provides a signal when a dream begins and ends.
  */
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 516b8c5..b0d134f 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -36,6 +36,11 @@
 import com.android.systemui.dreams.homecontrols.DreamActivityProvider;
 import com.android.systemui.dreams.homecontrols.DreamActivityProviderImpl;
 import com.android.systemui.dreams.homecontrols.HomeControlsDreamService;
+import com.android.systemui.qs.QsEventLogger;
+import com.android.systemui.qs.pipeline.shared.TileSpec;
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig;
+import com.android.systemui.qs.tiles.viewmodel.QSTilePolicy;
+import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig;
 import com.android.systemui.res.R;
 import com.android.systemui.touch.TouchInsetManager;
 
@@ -44,6 +49,7 @@
 import dagger.Provides;
 import dagger.multibindings.ClassKey;
 import dagger.multibindings.IntoMap;
+import dagger.multibindings.StringKey;
 
 import java.util.Optional;
 import java.util.concurrent.Executor;
@@ -70,6 +76,7 @@
     String DREAM_SUPPORTED = "dream_supported";
     String DREAM_OVERLAY_WINDOW_TITLE = "dream_overlay_window_title";
     String HOME_CONTROL_PANEL_DREAM_COMPONENT = "home_control_panel_dream_component";
+    String DREAM_TILE_SPEC = "dream";
 
     /**
      * Provides the dream component
@@ -178,6 +185,23 @@
         return resources.getString(R.string.app_label);
     }
 
+    /** Provides config for the dream tile */
+    @Provides
+    @IntoMap
+    @StringKey(DREAM_TILE_SPEC)
+    static QSTileConfig provideDreamTileConfig(QsEventLogger uiEventLogger) {
+        TileSpec tileSpec = TileSpec.create(DREAM_TILE_SPEC);
+        return new QSTileConfig(tileSpec,
+                new QSTileUIConfig.Resource(
+                        R.drawable.ic_qs_screen_saver,
+                        R.string.quick_settings_screensaver_label),
+                uiEventLogger.getNewInstanceId(),
+                tileSpec.getSpec(),
+                QSTilePolicy.NoRestrictions.INSTANCE
+                );
+    }
+
+
     /** Provides activity for dream service */
     @Binds
     DreamActivityProvider bindActivityProvider(DreamActivityProviderImpl impl);
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
index 72b0891..7d11d32 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java
@@ -25,6 +25,7 @@
 import static com.android.systemui.flags.FlagManager.EXTRA_VALUE;
 import static com.android.systemui.flags.FlagsCommonModule.ALL_FLAGS;
 import static com.android.systemui.shared.Flags.exampleSharedFlag;
+
 import static java.util.Objects.requireNonNull;
 
 import android.content.BroadcastReceiver;
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
index 8b1f8d3..67c5564 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
@@ -25,7 +25,6 @@
 import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
 import com.android.systemui.Flags.communalHub
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.flags.Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW
 import com.android.systemui.keyguard.KeyguardBottomAreaRefactor
 import com.android.systemui.keyguard.MigrateClocksToBlueprint
 import com.android.systemui.keyguard.shared.ComposeLockscreen
@@ -53,7 +52,6 @@
 
         // SceneContainer dependencies
         SceneContainerFlag.getFlagDependencies().forEach { (alpha, beta) -> alpha dependsOn beta }
-        SceneContainerFlag.getMainAconfigFlag() dependsOn MIGRATE_KEYGUARD_STATUS_BAR_VIEW
 
         // ComposeLockscreen dependencies
         ComposeLockscreen.token dependsOn KeyguardBottomAreaRefactor.token
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 04f1ad2..2e49919 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -178,16 +178,11 @@
 
     /** Flag meant to guard the talkback fix for the KeyguardIndicationTextView */
     // TODO(b/286563884): Tracking bug
-    @JvmField val KEYGUARD_TALKBACK_FIX = releasedFlag("keyguard_talkback_fix")
+    @JvmField val KEYGUARD_TALKBACK_FIX = unreleasedFlag("keyguard_talkback_fix")
 
     // TODO(b/287268101): Tracking bug.
     @JvmField val TRANSIT_CLOCK = releasedFlag("lockscreen_custom_transit_clock")
 
-    /** Migrate the status bar view on keyguard from notification panel to keyguard root view. */
-    // TODO(b/299115332): Tracking Bug.
-    @JvmField val MIGRATE_KEYGUARD_STATUS_BAR_VIEW =
-        unreleasedFlag("migrate_keyguard_status_bar_view")
-
     /** Enables preview loading animation in the wallpaper picker. */
     // TODO(b/274443705): Tracking Bug
     @JvmField
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
index f1a8faf..db2ec8f 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffect.kt
@@ -16,20 +16,14 @@
 
 package com.android.systemui.haptics.qs
 
-import android.animation.ValueAnimator
 import android.os.VibrationEffect
 import android.view.View
-import android.view.animation.AccelerateDecelerateInterpolator
 import androidx.annotation.VisibleForTesting
-import androidx.core.animation.doOnCancel
-import androidx.core.animation.doOnEnd
-import androidx.core.animation.doOnStart
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
 import com.android.systemui.statusbar.VibratorHelper
 import javax.inject.Inject
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
 
 /**
@@ -50,17 +44,14 @@
     keyguardInteractor: KeyguardInteractor,
 ) {
 
-    private var effectDuration = 0
+    var effectDuration = 0
+        private set
 
     /** Current state */
-    private var _state = MutableStateFlow(State.IDLE)
-    val state = _state.asStateFlow()
+    var state = State.IDLE
+        private set
 
-    /** Flows for view control and action */
-    private val _effectProgress = MutableStateFlow<Float?>(null)
-    val effectProgress = _effectProgress.asStateFlow()
-
-    // Actions to perform
+    /** Flow for view control and action */
     private val _postedActionType = MutableStateFlow<ActionType?>(null)
     val actionType: Flow<ActionType?> =
         combine(
@@ -85,29 +76,23 @@
 
     private val snapEffect = LongPressHapticBuilder.createSnapEffect()
 
-    private var effectAnimator: ValueAnimator? = null
-
     val hasInitialized: Boolean
-        get() = longPressHint != null && effectAnimator != null
+        get() = longPressHint != null
 
     @VisibleForTesting
-    fun setState(state: State) {
-        _state.value = state
+    fun setState(newState: State) {
+        state = newState
     }
 
-    private fun reverse() {
-        effectAnimator?.let {
-            val pausedProgress = it.animatedFraction
-            val effect =
-                LongPressHapticBuilder.createReversedEffect(
-                    pausedProgress,
-                    durations?.get(0) ?: 0,
-                    effectDuration,
-                )
-            vibratorHelper?.cancel()
-            vibrate(effect)
-            it.reverse()
-        }
+    fun playReverseHaptics(pausedProgress: Float) {
+        val effect =
+            LongPressHapticBuilder.createReversedEffect(
+                pausedProgress,
+                durations?.get(0) ?: 0,
+                effectDuration,
+            )
+        vibratorHelper?.cancel()
+        vibrate(effect)
     }
 
     private fun vibrate(effect: VibrationEffect?) {
@@ -117,23 +102,23 @@
     }
 
     fun handleActionDown() {
-        when (_state.value) {
+        when (state) {
             State.IDLE -> {
                 setState(State.TIMEOUT_WAIT)
             }
-            State.RUNNING_BACKWARDS -> effectAnimator?.cancel()
+            State.RUNNING_BACKWARDS -> _postedActionType.value = ActionType.CANCEL_ANIMATOR
             else -> {}
         }
     }
 
     fun handleActionUp() {
-        when (_state.value) {
+        when (state) {
             State.TIMEOUT_WAIT -> {
                 _postedActionType.value = ActionType.CLICK
                 setState(State.IDLE)
             }
             State.RUNNING_FORWARD -> {
-                reverse()
+                _postedActionType.value = ActionType.REVERSE_ANIMATOR
                 setState(State.RUNNING_BACKWARDS)
             }
             else -> {}
@@ -141,44 +126,42 @@
     }
 
     fun handleActionCancel() {
-        when (_state.value) {
+        when (state) {
             State.TIMEOUT_WAIT -> {
                 setState(State.IDLE)
             }
             State.RUNNING_FORWARD -> {
-                reverse()
+                _postedActionType.value = ActionType.REVERSE_ANIMATOR
                 setState(State.RUNNING_BACKWARDS)
             }
             else -> {}
         }
     }
 
-    private fun handleAnimationStart() {
+    fun handleAnimationStart() {
         vibrate(longPressHint)
         setState(State.RUNNING_FORWARD)
     }
 
     /** This function is called both when an animator completes or gets cancelled */
-    private fun handleAnimationComplete() {
-        if (_state.value == State.RUNNING_FORWARD) {
+    fun handleAnimationComplete() {
+        if (state == State.RUNNING_FORWARD) {
             vibrate(snapEffect)
             _postedActionType.value = ActionType.LONG_PRESS
-            _effectProgress.value = null
         }
-        if (_state.value != State.TIMEOUT_WAIT) {
+        if (state != State.TIMEOUT_WAIT) {
             // This will happen if the animator did not finish by being cancelled
             setState(State.IDLE)
         }
     }
 
-    private fun handleAnimationCancel() {
-        _effectProgress.value = null
+    fun handleAnimationCancel() {
         setState(State.TIMEOUT_WAIT)
     }
 
     fun handleTimeoutComplete() {
-        if (_state.value == State.TIMEOUT_WAIT && effectAnimator?.isRunning == false) {
-            effectAnimator?.start()
+        if (state == State.TIMEOUT_WAIT) {
+            _postedActionType.value = ActionType.START_ANIMATOR
         }
     }
 
@@ -186,18 +169,6 @@
         _postedActionType.value = null
     }
 
-    /** Reset the effect by going back to a default [IDLE] state */
-    fun resetEffect() {
-        if (effectAnimator?.isRunning == true) {
-            effectAnimator?.cancel()
-        }
-        longPressHint = null
-        effectAnimator = null
-        _effectProgress.value = null
-        _postedActionType.value = null
-        setState(State.IDLE)
-    }
-
     /**
      * Reset the effect with a new effect duration.
      *
@@ -205,27 +176,21 @@
      * @return true if the effect initialized correctly
      */
     fun initializeEffect(duration: Int): Boolean {
-        // The effect can't reset if it is running
+        // The effect can't initialize with a negative duration
         if (duration <= 0) return false
 
-        resetEffect()
-        effectDuration = duration
-        effectAnimator =
-            ValueAnimator.ofFloat(0f, 1f).apply {
-                this.duration = effectDuration.toLong()
-                interpolator = AccelerateDecelerateInterpolator()
+        // There is no need to re-initialize if the duration has not changed
+        if (duration == effectDuration) return true
 
-                doOnStart { handleAnimationStart() }
-                addUpdateListener { _effectProgress.value = animatedValue as Float }
-                doOnEnd { handleAnimationComplete() }
-                doOnCancel { handleAnimationCancel() }
-            }
+        effectDuration = duration
         longPressHint =
             LongPressHapticBuilder.createLongPressHint(
                 durations?.get(0) ?: LongPressHapticBuilder.INVALID_DURATION,
                 durations?.get(1) ?: LongPressHapticBuilder.INVALID_DURATION,
                 effectDuration
             )
+        _postedActionType.value = ActionType.INITIALIZE_ANIMATOR
+        setState(State.IDLE)
         return true
     }
 
@@ -241,5 +206,9 @@
         CLICK,
         LONG_PRESS,
         RESET_AND_LONG_PRESS,
+        START_ANIMATOR,
+        REVERSE_ANIMATOR,
+        CANCEL_ANIMATOR,
+        INITIALIZE_ANIMATOR,
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt
index dd7a285..c591af2 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/qs/QSLongPressEffectViewBinder.kt
@@ -16,9 +16,14 @@
 
 package com.android.systemui.haptics.qs
 
+import android.animation.ValueAnimator
 import android.annotation.SuppressLint
 import android.view.MotionEvent
 import android.view.ViewConfiguration
+import android.view.animation.AccelerateDecelerateInterpolator
+import androidx.core.animation.doOnCancel
+import androidx.core.animation.doOnEnd
+import androidx.core.animation.doOnStart
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.app.tracing.coroutines.launch
@@ -40,32 +45,63 @@
 
         return tile.repeatWhenAttached {
             repeatOnLifecycle(Lifecycle.State.CREATED) {
-                // Progress of the effect
-                launch({ "${tileSpec ?: "unknownTileSpec"}#LongPressEffect#progress" }) {
-                    qsLongPressEffect.effectProgress.collect { progress ->
-                        progress?.let {
-                            if (it == 0f) {
-                                tile.bringToFront()
-                            } else {
-                                tile.updateLongPressEffectProperties(it)
-                            }
-                        }
-                    }
-                }
-
                 // Action to perform
                 launch({ "${tileSpec ?: "unknownTileSpec"}#LongPressEffect#action" }) {
+                    var effectAnimator: ValueAnimator? = null
+
                     qsLongPressEffect.actionType.collect { action ->
                         action?.let {
                             when (it) {
-                                QSLongPressEffect.ActionType.CLICK -> tile.performClick()
-                                QSLongPressEffect.ActionType.LONG_PRESS -> tile.performLongClick()
+                                QSLongPressEffect.ActionType.CLICK -> {
+                                    tile.performClick()
+                                    qsLongPressEffect.clearActionType()
+                                }
+                                QSLongPressEffect.ActionType.LONG_PRESS -> {
+                                    tile.performLongClick()
+                                    qsLongPressEffect.clearActionType()
+                                }
                                 QSLongPressEffect.ActionType.RESET_AND_LONG_PRESS -> {
                                     tile.resetLongPressEffectProperties()
                                     tile.performLongClick()
+                                    qsLongPressEffect.clearActionType()
+                                }
+                                QSLongPressEffect.ActionType.START_ANIMATOR -> {
+                                    if (effectAnimator?.isRunning == false) {
+                                        effectAnimator?.start()
+                                    }
+                                }
+                                QSLongPressEffect.ActionType.REVERSE_ANIMATOR -> {
+                                    effectAnimator?.let {
+                                        val pausedProgress = it.animatedFraction
+                                        qsLongPressEffect.playReverseHaptics(pausedProgress)
+                                        it.reverse()
+                                    }
+                                }
+                                QSLongPressEffect.ActionType.CANCEL_ANIMATOR -> {
+                                    tile.resetLongPressEffectProperties()
+                                    effectAnimator?.cancel()
+                                }
+                                QSLongPressEffect.ActionType.INITIALIZE_ANIMATOR -> {
+                                    effectAnimator =
+                                        ValueAnimator.ofFloat(0f, 1f).apply {
+                                            this.duration =
+                                                qsLongPressEffect.effectDuration.toLong()
+                                            interpolator = AccelerateDecelerateInterpolator()
+
+                                            doOnStart { qsLongPressEffect.handleAnimationStart() }
+                                            addUpdateListener {
+                                                val value = animatedValue as Float
+                                                if (value == 0f) {
+                                                    tile.bringToFront()
+                                                } else {
+                                                    tile.updateLongPressEffectProperties(value)
+                                                }
+                                            }
+                                            doOnEnd { qsLongPressEffect.handleAnimationComplete() }
+                                            doOnCancel { qsLongPressEffect.handleAnimationCancel() }
+                                        }
                                 }
                             }
-                            qsLongPressEffect.clearActionType()
                         }
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index 17e3ca6..1fac7f1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -50,8 +50,8 @@
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.systemui.CoreStartable;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.util.settings.SecureSettings;
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index a5d7e04..ae163ea 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -89,14 +89,14 @@
 import com.android.wm.shell.shared.TransitionUtil;
 import com.android.wm.shell.transition.Transitions;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import java.util.ArrayList;
 import java.util.Map;
 import java.util.WeakHashMap;
 
 import javax.inject.Inject;
 
-import kotlinx.coroutines.CoroutineScope;
-
 public class KeyguardService extends Service {
     static final String TAG = "KeyguardService";
     static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 0d40511..dbaa297 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -48,10 +48,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.res.R;
 import com.android.systemui.SystemUIAppComponentFactoryBase;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.StatusBarState;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
index 4f02f75..39144b5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
@@ -30,10 +30,10 @@
 import androidx.annotation.Nullable;
 
 import com.android.systemui.Dumpable;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.power.domain.interactor.PowerInteractor;
+import com.android.systemui.res.R;
 import com.android.systemui.util.time.SystemClock;
 
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index 09875a5..2c5bacb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -37,8 +37,8 @@
 import android.window.OnBackInvokedDispatcher;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.res.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.res.R;
 
 import javax.inject.Inject;
 
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 7879ab6..4e6cfcc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -90,11 +90,11 @@
 import dagger.multibindings.ClassKey;
 import dagger.multibindings.IntoMap;
 
-import java.util.concurrent.Executor;
-
 import kotlinx.coroutines.CoroutineDispatcher;
 import kotlinx.coroutines.ExperimentalCoroutinesApi;
 
+import java.util.concurrent.Executor;
+
 /**
  * Dagger Module providing keyguard.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index c415081..1fba737 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -19,7 +19,6 @@
 import android.animation.ValueAnimator
 import com.android.app.animation.Interpolators
 import com.android.app.tracing.coroutines.launch
-import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
@@ -29,12 +28,13 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.keyguard.shared.model.TransitionModeOnCanceled
 import com.android.systemui.power.domain.interactor.PowerInteractor
-import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.kotlin.Utils.Companion.sample
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.debounce
 
 @SysUISingleton
@@ -49,8 +49,6 @@
     private val keyguardInteractor: KeyguardInteractor,
     powerInteractor: PowerInteractor,
     keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
-    private val lockPatternUtils: LockPatternUtils,
-    private val selectedUserInteractor: SelectedUserInteractor,
 ) :
     TransitionInteractor(
         fromState = KeyguardState.AOD,
@@ -65,10 +63,18 @@
         listenForAodToAwake()
         listenForAodToOccluded()
         listenForAodToPrimaryBouncer()
-        listenForAodToGone()
         listenForTransitionToCamera(scope, keyguardInteractor)
     }
 
+    private val canDismissLockscreen: Flow<Boolean> =
+        combine(
+            keyguardInteractor.isKeyguardShowing,
+            keyguardInteractor.isKeyguardDismissible,
+            keyguardInteractor.biometricUnlockState,
+        ) { isKeyguardShowing, isKeyguardDismissible, biometricUnlockState ->
+            (isWakeAndUnlock(biometricUnlockState) || (!isKeyguardShowing && isKeyguardDismissible))
+        }
+
     /**
      * Listen for the signal that we're waking up and figure what state we need to transition to.
      */
@@ -79,12 +85,13 @@
         scope.launch("$TAG#listenForAodToAwake") {
             powerInteractor.detailedWakefulness
                 .filterRelevantKeyguardStateAnd { wakefulness -> wakefulness.isAwake() }
+                .debounce(50L)
                 .sample(
                     startedKeyguardTransitionStep,
                     keyguardInteractor.biometricUnlockState,
                     keyguardInteractor.primaryBouncerShowing,
                     keyguardInteractor.isKeyguardOccluded,
-                    selectedUserInteractor.selectedUser,
+                    canDismissLockscreen,
                 )
                 .collect {
                     (
@@ -93,10 +100,9 @@
                         biometricUnlockState,
                         primaryBouncerShowing,
                         isKeyguardOccludedLegacy,
-                        currentUser,
+                        canDismissLockscreen,
                     ) ->
                     if (!maybeHandleInsecurePowerGesture()) {
-                        val securityNone = lockPatternUtils.isLockScreenDisabled(currentUser)
                         val shouldTransitionToLockscreen =
                             if (KeyguardWmStateRefactor.isEnabled) {
                                 // Check with the superclass to see if an occlusion transition is
@@ -105,13 +111,11 @@
                                 // completes.
                                 !maybeStartTransitionToOccludedOrInsecureCamera() &&
                                     !isWakeAndUnlock(biometricUnlockState) &&
-                                    !primaryBouncerShowing &&
-                                    !securityNone
+                                    !primaryBouncerShowing
                             } else {
                                 !isKeyguardOccludedLegacy &&
                                     !isWakeAndUnlock(biometricUnlockState) &&
-                                    !primaryBouncerShowing &&
-                                    !securityNone
+                                    !primaryBouncerShowing
                             }
 
                         // With the refactor enabled, maybeStartTransitionToOccludedOrInsecureCamera
@@ -119,7 +123,11 @@
                         val shouldTransitionToOccluded =
                             !KeyguardWmStateRefactor.isEnabled && isKeyguardOccludedLegacy
 
-                        if (shouldTransitionToLockscreen) {
+                        if (canDismissLockscreen) {
+                            startTransitionTo(
+                                toState = KeyguardState.GONE,
+                            )
+                        } else if (shouldTransitionToLockscreen) {
                             val modeOnCanceled =
                                 if (startedStep.from == KeyguardState.LOCKSCREEN) {
                                     TransitionModeOnCanceled.REVERSE
@@ -181,35 +189,6 @@
         }
     }
 
-    private fun listenForAodToGone() {
-        if (KeyguardWmStateRefactor.isEnabled) {
-            // Handled via #dismissAod.
-            return
-        }
-
-        scope.launch("$TAG#listenForAodToGone") {
-            powerInteractor.isAwake
-                .debounce(50L)
-                .filterRelevantKeyguardState()
-                .sample(
-                    keyguardInteractor.biometricUnlockState,
-                    keyguardInteractor.isKeyguardShowing,
-                    keyguardInteractor.isKeyguardDismissible,
-                )
-                .collect { (isAwake, biometricUnlockState, isKeyguardShowing, isKeyguardDismissible)
-                    ->
-                    KeyguardWmStateRefactor.assertInLegacyMode()
-                    if (
-                        isAwake &&
-                            (isWakeAndUnlock(biometricUnlockState) ||
-                                (!isKeyguardShowing && isKeyguardDismissible))
-                    ) {
-                        startTransitionTo(KeyguardState.GONE)
-                    }
-                }
-        }
-    }
-
     /**
      * Dismisses AOD and transitions to GONE. This is called whenever authentication occurs while on
      * AOD.
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 141cca3..e711edc 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
@@ -101,12 +101,6 @@
         }
 
         scope.launch {
-            keyguardInteractor.isKeyguardDismissible.collect {
-                logger.log(TAG, VERBOSE, "isKeyguardDismissable", it)
-            }
-        }
-
-        scope.launch {
             keyguardInteractor.isAbleToDream.collect {
                 logger.log(TAG, VERBOSE, "isAbleToDream", it)
             }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusBarSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusBarSection.kt
index f713d5e..9b5fae3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusBarSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusBarSection.kt
@@ -27,10 +27,9 @@
 import androidx.constraintlayout.widget.ConstraintSet.START
 import androidx.constraintlayout.widget.ConstraintSet.TOP
 import com.android.keyguard.dagger.KeyguardStatusBarViewComponent
-import com.android.systemui.res.R
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
 import com.android.systemui.keyguard.shared.model.KeyguardSection
+import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.NotificationPanelView
 import com.android.systemui.shade.ShadeViewStateProvider
 import com.android.systemui.statusbar.phone.KeyguardStatusBarView
@@ -42,7 +41,6 @@
 @Inject
 constructor(
     private val context: Context,
-    private val featureFlags: FeatureFlags,
     private val notificationPanelView: NotificationPanelView,
     private val keyguardStatusBarViewComponentFactory: KeyguardStatusBarViewComponent.Factory,
 ) : KeyguardSection() {
@@ -50,7 +48,7 @@
     private val statusBarViewId = R.id.keyguard_header
 
     override fun addViews(constraintLayout: ConstraintLayout) {
-        if (!featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW)) {
+        if (!SceneContainerFlag.isEnabled) {
             return
         }
 
@@ -67,7 +65,7 @@
     }
 
     override fun bindData(constraintLayout: ConstraintLayout) {
-        if (!featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW)) {
+        if (!SceneContainerFlag.isEnabled) {
             return
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
index 0bc60c4..7c29b39 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/transitions/ClockSizeTransition.kt
@@ -21,6 +21,7 @@
 import android.animation.ValueAnimator
 import android.graphics.Rect
 import android.transition.Transition
+import android.transition.TransitionListenerAdapter
 import android.transition.TransitionSet
 import android.transition.TransitionValues
 import android.util.Log
@@ -169,6 +170,18 @@
                     return@OnPreDrawListener true
                 }
 
+                this@VisibilityBoundsTransition.addListener(
+                    object : TransitionListenerAdapter() {
+                        override fun onTransitionStart(t: Transition) {
+                            toView.viewTreeObserver.addOnPreDrawListener(predrawCallback)
+                        }
+
+                        override fun onTransitionEnd(t: Transition) {
+                            toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
+                        }
+                    }
+                )
+
                 val listener =
                     object : AnimatorListenerAdapter() {
                         override fun onAnimationStart(anim: Animator) {
@@ -178,26 +191,11 @@
                         override fun onAnimationEnd(anim: Animator) {
                             assignAnimValues("end", 1f, toVis)
                             if (sendToBack) toView.translationZ = 0f
-                            toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
-                        }
-
-                        override fun onAnimationPause(anim: Animator) {
-                            toView.viewTreeObserver.removeOnPreDrawListener(predrawCallback)
-                        }
-
-                        override fun onAnimationResume(anim: Animator) {
-                            toView.viewTreeObserver.addOnPreDrawListener(predrawCallback)
                         }
                     }
 
-                anim.duration = duration
-                anim.startDelay = startDelay
-                anim.interpolator = interpolator
                 anim.addListener(listener)
-                anim.addPauseListener(listener)
-
                 assignAnimValues("init", 0f, fromVis)
-                toView.viewTreeObserver.addOnPreDrawListener(predrawCallback)
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java b/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java
index d01917a..fd526b9 100644
--- a/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java
@@ -45,7 +45,6 @@
 import com.android.internal.app.ILogAccessDialogCallback;
 import com.android.systemui.res.R;
 
-
 /**
  * Dialog responsible for obtaining user consent per-use log access
  */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
index df3a974..9719c02 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/data/repository/MediaFilterRepository.kt
@@ -16,24 +16,64 @@
 
 package com.android.systemui.media.controls.data.repository
 
+import android.content.Context
 import com.android.internal.logging.InstanceId
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.media.controls.data.model.MediaSortKeyModel
 import com.android.systemui.media.controls.shared.model.MediaCommonModel
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
+import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.time.SystemClock
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import java.util.Locale
 import java.util.TreeMap
 import javax.inject.Inject
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 
 /** A repository that holds the state of filtered media data on the device. */
 @SysUISingleton
-class MediaFilterRepository @Inject constructor(private val systemClock: SystemClock) {
+class MediaFilterRepository
+@Inject
+constructor(
+    @Application applicationContext: Context,
+    private val systemClock: SystemClock,
+    private val configurationController: ConfigurationController,
+) {
+
+    val onAnyMediaConfigurationChange: Flow<Unit> = conflatedCallbackFlow {
+        val callback =
+            object : ConfigurationController.ConfigurationListener {
+                override fun onDensityOrFontScaleChanged() {
+                    trySend(Unit)
+                }
+
+                override fun onThemeChanged() {
+                    trySend(Unit)
+                }
+
+                override fun onUiModeChanged() {
+                    trySend(Unit)
+                }
+
+                override fun onLocaleListChanged() {
+                    if (locale != applicationContext.resources.configuration.locales.get(0)) {
+                        locale = applicationContext.resources.configuration.locales.get(0)
+                        trySend(Unit)
+                    }
+                }
+            }
+        configurationController.addCallback(callback)
+        trySend(Unit)
+        awaitClose { configurationController.removeCallback(callback) }
+    }
 
     /** Instance id of media control that recommendations card reactivated. */
     private val _reactivatedId: MutableStateFlow<InstanceId?> = MutableStateFlow(null)
@@ -76,6 +116,7 @@
     val isMediaFromRec: StateFlow<Boolean> = _isMediaFromRec.asStateFlow()
 
     private var mediaFromRecPackageName: String? = null
+    private var locale: Locale = applicationContext.resources.configuration.locales.get(0)
 
     fun addMediaEntry(key: String, data: MediaData) {
         val entries = LinkedHashMap<String, MediaData>(_allUserEntries.value)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
index 13f934e..33c0b19 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaCarouselInteractor.kt
@@ -157,7 +157,7 @@
 
         // Set up links back into the pipeline for listeners that need to send events upstream.
         mediaTimeoutListener.timeoutCallback = { key: String, timedOut: Boolean ->
-            setInactive(key, timedOut)
+            mediaDataProcessor.setInactive(key, timedOut)
         }
         mediaTimeoutListener.stateCallback = { key: String, state: PlaybackState ->
             mediaDataProcessor.updateState(key, state)
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
index c0bb628..9f2d132 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaControlInteractor.kt
@@ -83,6 +83,8 @@
             .pairwiseBy(initialValue = false) { wasPlaying, isPlaying -> !wasPlaying && isPlaying }
             .distinctUntilChanged()
 
+    val onAnyMediaConfigurationChange: Flow<Unit> = repository.onAnyMediaConfigurationChange
+
     fun removeMediaControl(
         token: MediaSession.Token?,
         instanceId: InstanceId,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt
index dea5810..dd6b264 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/interactor/MediaRecommendationsInteractor.kt
@@ -65,6 +65,8 @@
             .distinctUntilChanged()
             .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
 
+    val onAnyMediaConfigurationChange: Flow<Unit> = repository.onAnyMediaConfigurationChange
+
     fun removeMediaRecommendations(key: String, dismissIntent: Intent?, delayMs: Long) {
         mediaDataProcessor.dismissSmartspaceRecommendation(key, delayMs)
         if (dismissIntent == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
index 8dd3379..73fb558 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaControlViewBinder.kt
@@ -100,7 +100,7 @@
         }
     }
 
-    private suspend fun bindMediaCard(
+    suspend fun bindMediaCard(
         viewHolder: MediaViewHolder,
         viewController: MediaViewController,
         viewModel: MediaPlayerViewModel,
@@ -333,7 +333,7 @@
                 }
             }
         }
-        updateSeekBarVisibility(viewController.expandedLayout, isSeekBarEnabled = false)
+        updateSeekBarVisibility(viewController.expandedLayout, viewController.isSeekBarEnabled)
     }
 
     private fun bindButtonCommon(
@@ -472,6 +472,7 @@
                             if (viewModel.shouldAddGradient) 333 else 80
                         )
                     }
+                        ?: albumView.setImageDrawable(artwork)
                 }
                 viewController.isArtworkBound = viewModel.shouldAddGradient
                 viewController.prevArtwork = artwork
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt
index fe13da6..bd4d435 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/binder/MediaRecommendationsViewBinder.kt
@@ -68,7 +68,7 @@
         }
     }
 
-    private fun bindRecsCard(
+    fun bindRecsCard(
         viewHolder: RecommendationViewHolder,
         viewModel: MediaRecsCardViewModel,
         mediaViewController: MediaViewController,
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
index d2dd289..0478178 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
@@ -35,6 +35,7 @@
 import androidx.annotation.VisibleForTesting
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
+import androidx.recyclerview.widget.DiffUtil
 import com.android.app.tracing.traceSection
 import com.android.internal.logging.InstanceId
 import com.android.keyguard.KeyguardUpdateMonitor
@@ -53,12 +54,18 @@
 import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
+import com.android.systemui.media.controls.ui.binder.MediaControlViewBinder
+import com.android.systemui.media.controls.ui.binder.MediaRecommendationsViewBinder
 import com.android.systemui.media.controls.ui.controller.MediaControlPanel.SMARTSPACE_CARD_DISMISS_EVENT
+import com.android.systemui.media.controls.ui.util.MediaViewModelCallback
+import com.android.systemui.media.controls.ui.util.MediaViewModelListUpdateCallback
 import com.android.systemui.media.controls.ui.view.MediaCarouselScrollHandler
 import com.android.systemui.media.controls.ui.view.MediaHostState
 import com.android.systemui.media.controls.ui.view.MediaScrollView
 import com.android.systemui.media.controls.ui.view.MediaViewHolder
 import com.android.systemui.media.controls.ui.view.RecommendationViewHolder
+import com.android.systemui.media.controls.ui.viewmodel.MediaCarouselViewModel
+import com.android.systemui.media.controls.ui.viewmodel.MediaCommonViewModel
 import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.media.controls.util.MediaUiEventLogger
 import com.android.systemui.media.controls.util.SmallHash
@@ -118,12 +125,13 @@
     private val mediaHostStatesManager: MediaHostStatesManager,
     private val activityStarter: ActivityStarter,
     private val systemClock: SystemClock,
+    @Main private val mainDispatcher: CoroutineDispatcher,
     @Main executor: DelayableExecutor,
     @Background private val bgExecutor: Executor,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val mediaManager: MediaDataManager,
     configurationController: ConfigurationController,
-    falsingManager: FalsingManager,
+    private val falsingManager: FalsingManager,
     dumpManager: DumpManager,
     private val logger: MediaUiEventLogger,
     private val debugLogger: MediaCarouselControllerLogger,
@@ -132,6 +140,8 @@
     private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
     private val globalSettings: GlobalSettings,
     private val secureSettings: SecureSettings,
+    private val mediaCarouselViewModel: MediaCarouselViewModel,
+    private val mediaViewControllerFactory: Provider<MediaViewController>,
 ) : Dumpable {
     /** The current width of the carousel */
     var currentCarouselWidth: Int = 0
@@ -182,7 +192,6 @@
         private set
     private val mediaContent: ViewGroup
     @VisibleForTesting var pageIndicator: PageIndicator
-    private val visualStabilityCallback: OnReorderingAllowedListener
     private var needsReordering: Boolean = false
     private var keysNeedRemoval = mutableSetOf<String>()
     var shouldScrollToKey: Boolean = false
@@ -201,7 +210,11 @@
     private val animationScaleObserver: ContentObserver =
         object : ContentObserver(null) {
             override fun onChange(selfChange: Boolean) {
-                MediaPlayerData.players().forEach { it.updateAnimatorDurationScale() }
+                if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+                    MediaPlayerData.players().forEach { it.updateAnimatorDurationScale() }
+                } else {
+                    controllerByViewModel.values.forEach { it.updateAnimatorDurationScale() }
+                }
             }
         }
 
@@ -297,6 +310,9 @@
     private var widthInSceneContainerPx = 0
     private var heightInSceneContainerPx = 0
 
+    private val controllerByViewModel = mutableMapOf<MediaCommonViewModel, MediaViewController>()
+    private val commonViewModels = mutableListOf<MediaCommonViewModel>()
+
     init {
         dumpManager.registerDumpable(TAG, this)
         mediaFrame = inflateMediaCarousel()
@@ -320,7 +336,48 @@
         inflateSettingsButton()
         mediaContent = mediaCarousel.requireViewById(R.id.media_carousel)
         configurationController.addCallback(configListener)
-        visualStabilityCallback = OnReorderingAllowedListener {
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+            setUpListeners()
+        }
+        mediaFrame.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
+            // The pageIndicator is not laid out yet when we get the current state update,
+            // Lets make sure we have the right dimensions
+            updatePageIndicatorLocation()
+        }
+        mediaHostStatesManager.addCallback(
+            object : MediaHostStatesManager.Callback {
+                override fun onHostStateChanged(
+                    @MediaLocation location: Int,
+                    mediaHostState: MediaHostState
+                ) {
+                    updateUserVisibility()
+                    if (location == desiredLocation) {
+                        onDesiredLocationChanged(desiredLocation, mediaHostState, animate = false)
+                    }
+                }
+            }
+        )
+        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
+        mediaCarousel.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.STARTED) {
+                listenForAnyStateToGoneKeyguardTransition(this)
+                listenForAnyStateToLockscreenTransition(this)
+                listenForLockscreenSettingChanges(this)
+
+                if (!mediaFlags.isMediaControlsRefactorEnabled()) return@repeatOnLifecycle
+                listenForMediaItemsChanges(this)
+            }
+        }
+
+        // Notifies all active players about animation scale changes.
+        globalSettings.registerContentObserver(
+            Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
+            animationScaleObserver
+        )
+    }
+
+    private fun setUpListeners() {
+        val visualStabilityCallback = OnReorderingAllowedListener {
             if (needsReordering) {
                 needsReordering = false
                 reorderAllPlayers(previousVisiblePlayerKey = null)
@@ -530,35 +587,6 @@
                 }
             }
         )
-        mediaFrame.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
-            // The pageIndicator is not laid out yet when we get the current state update,
-            // Lets make sure we have the right dimensions
-            updatePageIndicatorLocation()
-        }
-        mediaHostStatesManager.addCallback(
-            object : MediaHostStatesManager.Callback {
-                override fun onHostStateChanged(location: Int, mediaHostState: MediaHostState) {
-                    updateUserVisibility()
-                    if (location == desiredLocation) {
-                        onDesiredLocationChanged(desiredLocation, mediaHostState, animate = false)
-                    }
-                }
-            }
-        )
-        keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
-        mediaCarousel.repeatWhenAttached {
-            repeatOnLifecycle(Lifecycle.State.STARTED) {
-                listenForAnyStateToGoneKeyguardTransition(this)
-                listenForAnyStateToLockscreenTransition(this)
-                listenForLockscreenSettingChanges(this)
-            }
-        }
-
-        // Notifies all active players about animation scale changes.
-        globalSettings.registerContentObserver(
-            Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),
-            animationScaleObserver
-        )
     }
 
     private fun inflateSettingsButton() {
@@ -642,6 +670,125 @@
         }
     }
 
+    private fun listenForMediaItemsChanges(scope: CoroutineScope): Job {
+        return scope.launch {
+            mediaCarouselViewModel.mediaItems.collectLatest {
+                val diffUtilCallback = MediaViewModelCallback(commonViewModels, it)
+                val listUpdateCallback =
+                    MediaViewModelListUpdateCallback(
+                        old = commonViewModels,
+                        new = it,
+                        onAdded = this@MediaCarouselController::onAdded,
+                        onUpdated = this@MediaCarouselController::onUpdated,
+                        onRemoved = this@MediaCarouselController::onRemoved,
+                        onMoved = this@MediaCarouselController::onMoved,
+                    )
+                DiffUtil.calculateDiff(diffUtilCallback).dispatchUpdatesTo(listUpdateCallback)
+                setNewViewModelsList(it)
+            }
+        }
+    }
+
+    private fun onAdded(commonViewModel: MediaCommonViewModel, position: Int) {
+        val viewController = mediaViewControllerFactory.get()
+        viewController.sizeChangedListener = this::updateCarouselDimensions
+        val lp =
+            LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT
+            )
+        when (commonViewModel) {
+            is MediaCommonViewModel.MediaControl -> {
+                val viewHolder = MediaViewHolder.create(LayoutInflater.from(context), mediaContent)
+                if (mediaFlags.isSceneContainerEnabled()) {
+                    viewController.widthInSceneContainerPx = widthInSceneContainerPx
+                    viewController.heightInSceneContainerPx = heightInSceneContainerPx
+                }
+                viewController.attachPlayer(viewHolder)
+                viewController.mediaViewHolder.player.layoutParams = lp
+                MediaControlViewBinder.bind(
+                    viewHolder,
+                    commonViewModel.controlViewModel,
+                    viewController,
+                    falsingManager,
+                    backgroundDispatcher,
+                    mainDispatcher,
+                    mediaFlags
+                )
+                mediaContent.addView(viewHolder.player, position)
+            }
+            is MediaCommonViewModel.MediaRecommendations -> {
+                val viewHolder =
+                    RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent)
+                viewController.attachRecommendations(viewHolder)
+                viewController.recommendationViewHolder.recommendations.layoutParams = lp
+                MediaRecommendationsViewBinder.bind(
+                    viewHolder,
+                    commonViewModel.recsViewModel,
+                    viewController,
+                    falsingManager,
+                )
+                mediaContent.addView(viewHolder.recommendations, position)
+            }
+        }
+        viewController.setListening(mediaCarouselScrollHandler.visibleToUser && currentlyExpanded)
+        updateViewControllerToState(viewController, noAnimation = true)
+        updatePageIndicator()
+        mediaCarouselScrollHandler.onPlayersChanged()
+        mediaFrame.requiresRemeasuring = true
+        commonViewModel.onAdded(commonViewModel)
+        controllerByViewModel[commonViewModel] = viewController
+    }
+
+    private fun onUpdated(commonViewModel: MediaCommonViewModel) {
+        commonViewModel.onUpdated(commonViewModel)
+        updatePageIndicator()
+        mediaCarouselScrollHandler.onPlayersChanged()
+    }
+
+    private fun onRemoved(commonViewModel: MediaCommonViewModel) {
+        controllerByViewModel.remove(commonViewModel)?.let {
+            when (commonViewModel) {
+                is MediaCommonViewModel.MediaControl -> {
+                    mediaCarouselScrollHandler.onPrePlayerRemoved(it.mediaViewHolder.player)
+                    mediaContent.removeView(it.mediaViewHolder.player)
+                }
+                is MediaCommonViewModel.MediaRecommendations -> {
+                    mediaContent.removeView(it.recommendationViewHolder.recommendations)
+                }
+            }
+            it.onDestroy()
+            mediaCarouselScrollHandler.onPlayersChanged()
+            updatePageIndicator()
+            commonViewModel.onRemoved(true)
+        }
+    }
+
+    private fun onMoved(commonViewModel: MediaCommonViewModel, from: Int, to: Int) {
+        controllerByViewModel[commonViewModel]?.let {
+            mediaContent.removeViewAt(from)
+            when (commonViewModel) {
+                is MediaCommonViewModel.MediaControl -> {
+                    mediaContent.addView(it.mediaViewHolder.player, to)
+                }
+                is MediaCommonViewModel.MediaRecommendations -> {
+                    mediaContent.addView(it.recommendationViewHolder.recommendations, to)
+                }
+            }
+        }
+        updatePageIndicator()
+        mediaCarouselScrollHandler.onPlayersChanged()
+    }
+
+    private fun setNewViewModelsList(viewModels: List<MediaCommonViewModel>) {
+        commonViewModels.clear()
+        commonViewModels.addAll(viewModels)
+
+        // Ensure we only show the needed UMOs in media carousel.
+        val viewSet = viewModels.toHashSet()
+        controllerByViewModel.filter { !viewSet.contains(it.key) }.forEach { onRemoved(it.key) }
+    }
+
     private suspend fun getMediaLockScreenSetting(): Boolean {
         return withContext(backgroundDispatcher) {
             secureSettings.getBoolForUser(
@@ -758,7 +905,7 @@
                     isSsReactivated,
                     debugLogger
                 )
-                updatePlayerToState(newPlayer.mediaViewController, noAnimation = true)
+                updateViewControllerToState(newPlayer.mediaViewController, noAnimation = true)
                 // Media data added from a recommendation card should starts playing.
                 if (
                     (shouldScrollToKey && data.isPlaying == true) ||
@@ -856,7 +1003,7 @@
                 systemClock,
                 debugLogger,
             )
-            updatePlayerToState(newRecs.mediaViewController, noAnimation = true)
+            updateViewControllerToState(newRecs.mediaViewController, noAnimation = true)
             reorderAllPlayers(curVisibleMediaKey)
             updatePageIndicator()
             mediaFrame.requiresRemeasuring = true
@@ -905,6 +1052,10 @@
     }
 
     private fun updatePlayers(recreateMedia: Boolean) {
+        if (mediaFlags.isMediaControlsRefactorEnabled()) {
+            updateMediaPlayers(recreateMedia)
+            return
+        }
         pageIndicator.tintList =
             ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
         val previousVisibleKey =
@@ -940,6 +1091,28 @@
         }
     }
 
+    private fun updateMediaPlayers(recreateMedia: Boolean) {
+        pageIndicator.tintList =
+            ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+        if (recreateMedia) {
+            mediaContent.removeAllViews()
+            commonViewModels.forEach { viewModel ->
+                when (viewModel) {
+                    is MediaCommonViewModel.MediaControl -> {
+                        controllerByViewModel[viewModel]?.mediaViewHolder?.let {
+                            mediaContent.addView(it.player)
+                        }
+                    }
+                    is MediaCommonViewModel.MediaRecommendations -> {
+                        controllerByViewModel[viewModel]?.recommendationViewHolder?.let {
+                            mediaContent.addView(it.recommendations)
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private fun updatePageIndicator() {
         val numPages = mediaContent.getChildCount()
         pageIndicator.setNumPages(numPages)
@@ -979,8 +1152,14 @@
             currentStartLocation = startLocation
             currentEndLocation = endLocation
             currentTransitionProgress = progress
-            for (mediaPlayer in MediaPlayerData.players()) {
-                updatePlayerToState(mediaPlayer.mediaViewController, immediately)
+            if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+                for (mediaPlayer in MediaPlayerData.players()) {
+                    updateViewControllerToState(mediaPlayer.mediaViewController, immediately)
+                }
+            } else {
+                controllerByViewModel.values.forEach {
+                    updateViewControllerToState(it, immediately)
+                }
             }
             maybeResetSettingsCog()
             updatePageIndicatorAlpha()
@@ -1035,8 +1214,14 @@
 
     /** Update listening to seekbar. */
     private fun updateSeekbarListening(visibleToUser: Boolean) {
-        for (player in MediaPlayerData.players()) {
-            player.setListening(visibleToUser && currentlyExpanded)
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+            for (player in MediaPlayerData.players()) {
+                player.setListening(visibleToUser && currentlyExpanded)
+            }
+        } else {
+            controllerByViewModel.values.forEach {
+                it.setListening(visibleToUser && currentlyExpanded)
+            }
         }
     }
 
@@ -1044,12 +1229,22 @@
     private fun updateCarouselDimensions() {
         var width = 0
         var height = 0
-        for (mediaPlayer in MediaPlayerData.players()) {
-            val controller = mediaPlayer.mediaViewController
-            // When transitioning the view to gone, the view gets smaller, but the translation
-            // Doesn't, let's add the translation
-            width = Math.max(width, controller.currentWidth + controller.translationX.toInt())
-            height = Math.max(height, controller.currentHeight + controller.translationY.toInt())
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+            for (mediaPlayer in MediaPlayerData.players()) {
+                val controller = mediaPlayer.mediaViewController
+                // When transitioning the view to gone, the view gets smaller, but the translation
+                // Doesn't, let's add the translation
+                width = Math.max(width, controller.currentWidth + controller.translationX.toInt())
+                height =
+                    Math.max(height, controller.currentHeight + controller.translationY.toInt())
+            }
+        } else {
+            controllerByViewModel.values.forEach {
+                // When transitioning the view to gone, the view gets smaller, but the translation
+                // Doesn't, let's add the translation
+                width = Math.max(width, it.currentWidth + it.translationX.toInt())
+                height = Math.max(height, it.currentHeight + it.translationY.toInt())
+            }
         }
         if (width != currentCarouselWidth || height != currentCarouselHeight) {
             currentCarouselWidth = width
@@ -1080,7 +1275,10 @@
         }
     }
 
-    private fun updatePlayerToState(viewController: MediaViewController, noAnimation: Boolean) {
+    private fun updateViewControllerToState(
+        viewController: MediaViewController,
+        noAnimation: Boolean
+    ) {
         viewController.setCurrentState(
             startLocation = currentStartLocation,
             endLocation = currentEndLocation,
@@ -1123,18 +1321,31 @@
                         !mediaManager.hasActiveMediaOrRecommendation() &&
                         desiredHostState.showsOnlyActiveMedia
 
-                for (mediaPlayer in MediaPlayerData.players()) {
-                    if (animate) {
-                        mediaPlayer.mediaViewController.animatePendingStateChange(
-                            duration = duration,
-                            delay = startDelay
-                        )
-                    }
-                    if (shouldCloseGuts && mediaPlayer.mediaViewController.isGutsVisible) {
-                        mediaPlayer.closeGuts(!animate)
-                    }
+                if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+                    for (mediaPlayer in MediaPlayerData.players()) {
+                        if (animate) {
+                            mediaPlayer.mediaViewController.animatePendingStateChange(
+                                duration = duration,
+                                delay = startDelay
+                            )
+                        }
+                        if (shouldCloseGuts && mediaPlayer.mediaViewController.isGutsVisible) {
+                            mediaPlayer.closeGuts(!animate)
+                        }
 
-                    mediaPlayer.mediaViewController.onLocationPreChange(desiredLocation)
+                        mediaPlayer.mediaViewController.onLocationPreChange(desiredLocation)
+                    }
+                } else {
+                    controllerByViewModel.values.forEach { controller ->
+                        if (animate) {
+                            controller.animatePendingStateChange(duration, startDelay)
+                        }
+                        if (shouldCloseGuts && controller.isGutsVisible) {
+                            controller.closeGuts(!animate)
+                        }
+
+                        controller.onLocationPreChange(desiredLocation)
+                    }
                 }
                 mediaCarouselScrollHandler.showsSettingsButton = !it.showsOnlyActiveMedia
                 mediaCarouselScrollHandler.falsingProtectionNeeded = it.falsingProtectionNeeded
@@ -1150,7 +1361,11 @@
         }
 
     fun closeGuts(immediate: Boolean = true) {
-        MediaPlayerData.players().forEach { it.closeGuts(immediate) }
+        if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+            MediaPlayerData.players().forEach { it.closeGuts(immediate) }
+        } else {
+            controllerByViewModel.values.forEach { it.closeGuts(immediate) }
+        }
     }
 
     /** Update the size of the carousel, remeasuring it if necessary. */
@@ -1288,6 +1503,10 @@
     }
 
     private fun onSwipeToDismiss() {
+        if (mediaFlags.isMediaControlsRefactorEnabled()) {
+            mediaCarouselViewModel.onSwipeToDismiss()
+            return
+        }
         MediaPlayerData.players().forEachIndexed { index, it ->
             if (it.mIsImpressed) {
                 logSmartspaceCardReported(
@@ -1319,6 +1538,7 @@
             println("dataKeys: ${MediaPlayerData.dataKeys()}")
             println("orderedPlayerSortKeys: ${MediaPlayerData.playerKeys()}")
             println("visiblePlayerSortKeys: ${MediaPlayerData.visiblePlayerKeys()}")
+            println("commonViewModels: $commonViewModels")
             println("smartspaceMediaData: ${MediaPlayerData.smartspaceMediaData}")
             println("shouldPrioritizeSs: ${MediaPlayerData.shouldPrioritizeSs}")
             println("current size: $currentCarouselWidth x $currentCarouselHeight")
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
index 5188132..96a8239 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModel.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.util.Utils
 import com.android.systemui.util.kotlin.pairwiseBy
 import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import java.util.concurrent.Executor
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
@@ -50,6 +51,7 @@
     @Application private val applicationScope: CoroutineScope,
     @Application private val applicationContext: Context,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
+    @Background private val backgroundExecutor: Executor,
     private val visualStabilityProvider: VisualStabilityProvider,
     private val interactor: MediaCarouselInteractor,
     private val controlInteractorFactory: MediaControlInteractorFactory,
@@ -142,9 +144,9 @@
 
     private fun createMediaControlViewModel(instanceId: InstanceId): MediaControlViewModel {
         return MediaControlViewModel(
-            applicationScope = applicationScope,
             applicationContext = applicationContext,
             backgroundDispatcher = backgroundDispatcher,
+            backgroundExecutor = backgroundExecutor,
             interactor = controlInteractorFactory.create(instanceId),
             logger = logger,
         )
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
index 52e49d6..bc364c3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModel.kt
@@ -41,21 +41,21 @@
 import com.android.systemui.monet.Style
 import com.android.systemui.res.R
 import com.android.systemui.util.kotlin.sample
+import java.util.concurrent.Executor
 import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOn
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
 /** Models UI state and handles user input for a media control. */
 class MediaControlViewModel(
     @Application private val applicationContext: Context,
-    @Application private val applicationScope: CoroutineScope,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
+    @Background private val backgroundExecutor: Executor,
     private val interactor: MediaControlInteractor,
     private val logger: MediaUiEventLogger,
 ) {
@@ -72,9 +72,15 @@
                 .distinctUntilChanged()
         )
 
+    @OptIn(ExperimentalCoroutinesApi::class)
     val player: Flow<MediaPlayerViewModel?> =
-        combine(playTurbulenceNoise, interactor.mediaControl) { playTurbulenceNoise, mediaControl ->
-                mediaControl?.let { toViewModel(it, playTurbulenceNoise) }
+        interactor.onAnyMediaConfigurationChange
+            .flatMapLatest {
+                combine(playTurbulenceNoise, interactor.mediaControl) {
+                    playTurbulenceNoise,
+                    mediaControl ->
+                    mediaControl?.let { toViewModel(it, playTurbulenceNoise) }
+                }
             }
             .distinctUntilChanged()
             .flowOn(backgroundDispatcher)
@@ -161,12 +167,10 @@
                 if (model.isResume && model.resumeProgress != null) {
                     seekBarViewModel.updateStaticProgress(model.resumeProgress)
                 } else {
-                    applicationScope.launch {
-                        withContext(backgroundDispatcher) {
-                            seekBarViewModel.updateController(
-                                model.token?.let { MediaController(applicationContext, it) }
-                            )
-                        }
+                    backgroundExecutor.execute {
+                        seekBarViewModel.updateController(
+                            model.token?.let { MediaController(applicationContext, it) }
+                        )
                     }
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt
index 5cd9804..52c4bc5 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/MediaRecommendationsViewModel.kt
@@ -50,8 +50,10 @@
 import com.android.systemui.res.R
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOn
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.withContext
@@ -67,9 +69,12 @@
     private val logger: MediaUiEventLogger,
 ) {
 
+    @OptIn(ExperimentalCoroutinesApi::class)
     val mediaRecsCard: Flow<MediaRecsCardViewModel?> =
-        interactor.recommendations
-            .map { recsCard -> toRecsViewModel(recsCard) }
+        interactor.onAnyMediaConfigurationChange
+            .flatMapLatest {
+                interactor.recommendations.map { recsCard -> toRecsViewModel(recsCard) }
+            }
             .distinctUntilChanged()
             .flowOn(backgroundDispatcher)
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt
index 22b3f35..cef1e69 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt
@@ -33,19 +33,12 @@
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import com.android.systemui.classifier.Classifier.MEDIA_SEEKBAR
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.statusbar.NotificationMediaManager
 import com.android.systemui.util.concurrency.RepeatableExecutor
 import javax.inject.Inject
 import kotlin.math.abs
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
 private const val POSITION_UPDATE_INTERVAL_MILLIS = 100L
 private const val MIN_FLING_VELOCITY_SCALE_FACTOR = 10
@@ -88,11 +81,8 @@
 class SeekBarViewModel
 @Inject
 constructor(
-    @Application private val applicationScope: CoroutineScope,
-    @Main private val mainDispatcher: CoroutineDispatcher,
     @Background private val bgExecutor: RepeatableExecutor,
     private val falsingManager: FalsingManager,
-    private val mediaFlags: MediaFlags,
 ) {
     private var _data =
         Progress(
@@ -118,19 +108,9 @@
     private var controller: MediaController? = null
         set(value) {
             if (field?.sessionToken != value?.sessionToken) {
-                if (!mediaFlags.isMediaControlsRefactorEnabled()) {
-                    field?.unregisterCallback(callback)
-                    value?.registerCallback(callback)
-                    field = value
-                } else {
-                    applicationScope.launch {
-                        withContext(mainDispatcher) {
-                            field?.unregisterCallback(callback)
-                            value?.registerCallback(callback)
-                            field = value
-                        }
-                    }
-                }
+                field?.unregisterCallback(callback)
+                value?.registerCallback(callback)
+                field = value
             }
         }
     private var playbackState: PlaybackState? = null
diff --git a/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java b/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java
index 9de2b4f..74af4ee 100644
--- a/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/systemsounds/HomeSoundEffectController.java
@@ -26,8 +26,8 @@
 import android.util.Slog;
 
 import com.android.systemui.CoreStartable;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.res.R;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.shared.system.TaskStackChangeListeners;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarComponent.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarComponent.java
index 1d792af..4f713d6 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarComponent.java
@@ -25,14 +25,14 @@
 
 import com.android.systemui.dagger.qualifiers.DisplayId;
 
+import dagger.BindsInstance;
+import dagger.Subcomponent;
+
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
 
 import javax.inject.Scope;
 
-import dagger.BindsInstance;
-import dagger.Subcomponent;
-
 /**
  * Subcomponent for a NavigationBar.
  *
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
index 12f2703..b177b0b 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java
@@ -74,7 +74,6 @@
 
 import javax.inject.Inject;
 
-
 @SysUISingleton
 public class NavigationBarControllerImpl implements
         ConfigurationController.ConfigurationListener,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java
index c1d98c9..2ae0709 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarInflaterView.java
@@ -36,12 +36,12 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
 import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
 import com.android.systemui.navigationbar.buttons.KeyButtonView;
 import com.android.systemui.navigationbar.buttons.ReverseLinearLayout;
 import com.android.systemui.navigationbar.buttons.ReverseLinearLayout.ReverseRelativeLayout;
 import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.res.R;
 import com.android.systemui.shared.system.QuickStepContract;
 
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java
index 3ef5094..aab4fea 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java
@@ -21,10 +21,10 @@
 import android.view.View;
 import android.view.WindowManager;
 
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.DisplayId;
 import com.android.systemui.navigationbar.NavigationBarComponent.NavigationBarScope;
 import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
+import com.android.systemui.res.R;
 
 import dagger.Module;
 import dagger.Provides;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
index 3e34318..201e586 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarTransitions.java
@@ -24,9 +24,9 @@
 import android.util.SparseArray;
 import android.view.View;
 
-import com.android.systemui.res.R;
 import com.android.systemui.navigationbar.NavigationBarComponent.NavigationBarScope;
 import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.DisplayTracker;
 import com.android.systemui.statusbar.phone.BarTransitions;
 import com.android.systemui.statusbar.phone.LightBarTransitionsController;
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/ScreenPinningNotify.java b/packages/SystemUI/src/com/android/systemui/navigationbar/ScreenPinningNotify.java
index 939c096..1e40dd9 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/ScreenPinningNotify.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/ScreenPinningNotify.java
@@ -21,8 +21,8 @@
 import android.util.Slog;
 import android.widget.Toast;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysUIToast;
+import com.android.systemui.res.R;
 
 /**
  *  Helper to manage showing/hiding a image to notify them that they are entering or exiting screen
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/DeadZone.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/DeadZone.java
index bd3a0c1..3268306 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/DeadZone.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/DeadZone.java
@@ -26,9 +26,9 @@
 import android.view.Surface;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
 import com.android.systemui.navigationbar.NavigationBarController;
 import com.android.systemui.navigationbar.NavigationBarView;
+import com.android.systemui.res.R;
 
 import javax.inject.Inject;
 
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 b50ee57..933065b 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -516,9 +516,9 @@
                         SystemUiDeviceConfigFlags.BACK_GESTURE_SLOP_MULTIPLIER, 0.75f);
         mTouchSlop = mViewConfiguration.getScaledTouchSlop() * backGestureSlop;
         mBackSwipeLinearThreshold = res.getDimension(
-                R.dimen.navigation_edge_action_progress_threshold);
+                com.android.internal.R.dimen.navigation_edge_action_progress_threshold);
         mNonLinearFactor = getDimenFloat(res,
-                R.dimen.back_progress_non_linear_factor);
+                com.android.internal.R.dimen.back_progress_non_linear_factor);
         updateBackAnimationThresholds();
     }
 
@@ -1094,15 +1094,12 @@
                         return;
                     } else if (dx > dy && dx > mTouchSlop) {
                         if (mAllowGesture) {
-                            mThresholdCrossed = true;
-                            // Capture inputs
-                            mInputMonitor.pilferPointers();
                             if (mBackAnimation != null) {
-                                mBackAnimation.onPilferPointers();
-                                // Notify FalsingManager that an intentional gesture has occurred.
-                                mFalsingManager.isFalseTouch(BACK_GESTURE);
+                                mBackAnimation.onThresholdCrossed();
+                            } else {
+                                pilferPointers();
                             }
-                            mInputEventReceiver.setBatchingEnabled(true);
+                            mThresholdCrossed = true;
                         } else {
                             logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_FAR_FROM_EDGE);
                         }
@@ -1118,6 +1115,14 @@
         }
     }
 
+    private void pilferPointers() {
+        // Capture inputs
+        mInputMonitor.pilferPointers();
+        // Notify FalsingManager that an intentional gesture has occurred.
+        mFalsingManager.isFalseTouch(BACK_GESTURE);
+        mInputEventReceiver.setBatchingEnabled(true);
+    }
+
     private boolean isButtonPressFromTrackpad(MotionEvent ev) {
         // We don't allow back for button press from the trackpad, and yet we do with a mouse.
         int sources = InputManager.getInstance().getInputDevice(ev.getDeviceId()).getSources();
@@ -1266,6 +1271,9 @@
 
     public void setBackAnimation(BackAnimation backAnimation) {
         mBackAnimation = backAnimation;
+        mBackAnimation.setPilferPointerCallback(() -> {
+            pilferPointers();
+        });
         updateBackAnimationThresholds();
         if (mLightBarControllerProvider.get() != null) {
             mBackAnimation.setStatusBarCustomizer((appearance) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index 188e867..d23d3f6 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -55,9 +55,9 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.MessagingMessage;
 import com.android.settingslib.utils.ThreadUtils;
-import com.android.systemui.res.R;
 import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
 import com.android.systemui.people.widget.PeopleTileKey;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
 import java.text.SimpleDateFormat;
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
index ef72967..9b57b40 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
@@ -74,11 +74,11 @@
 import androidx.core.math.MathUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.res.R;
 import com.android.systemui.people.data.model.PeopleTileModel;
 import com.android.systemui.people.widget.LaunchConversationActivity;
 import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
 import com.android.systemui.people.widget.PeopleTileKey;
+import com.android.systemui.res.R;
 
 import java.io.IOException;
 import java.text.NumberFormat;
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
index e6575d5a..c65742c 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
@@ -19,11 +19,11 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.plugins.PluginDependency.DependencyProvider;
 
+import dagger.Lazy;
+
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import dagger.Lazy;
-
 /**
  */
 @Singleton
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
index 1f66b84..dbdec6b 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginsModule.java
@@ -21,9 +21,9 @@
 import android.content.pm.PackageManager;
 import android.os.Build;
 
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.PluginModule;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
 import com.android.systemui.shared.plugins.PluginActionManager;
 import com.android.systemui.shared.plugins.PluginEnabler;
 import com.android.systemui.shared.plugins.PluginInstance;
@@ -33,6 +33,10 @@
 import com.android.systemui.util.concurrency.GlobalConcurrencyModule;
 import com.android.systemui.util.concurrency.ThreadFactory;
 
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.Executor;
@@ -40,10 +44,6 @@
 import javax.inject.Named;
 import javax.inject.Singleton;
 
-import dagger.Binds;
-import dagger.Module;
-import dagger.Provides;
-
 /**
  * Dagger Module for code related to plugins.
  *
diff --git a/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java b/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java
index 8dd0ea0..b889f8e 100644
--- a/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java
+++ b/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java
@@ -30,7 +30,6 @@
 import dagger.multibindings.IntoMap;
 import dagger.multibindings.IntoSet;
 
-
 /** Dagger Module for code in the power package. */
 @Module(
         includes = {
diff --git a/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java b/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
index b6a5ad6..694b525 100644
--- a/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
@@ -20,10 +20,10 @@
 import com.android.systemui.process.ProcessWrapper;
 import com.android.systemui.shared.condition.Condition;
 
-import javax.inject.Inject;
-
 import kotlinx.coroutines.CoroutineScope;
 
+import javax.inject.Inject;
+
 /**
  * {@link SystemProcessCondition} checks to make sure the current process is being ran by the
  * System User.
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 d40112f..3907a72 100644
--- a/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qrcodescanner/dagger/QRCodeScannerModule.kt
@@ -16,10 +16,16 @@
 
 package com.android.systemui.qrcodescanner.dagger
 
+import com.android.systemui.qs.QsEventLogger
+import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.qs.tiles.QRCodeScannerTile
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
+import com.android.systemui.res.R
 import dagger.Binds
 import dagger.Module
+import dagger.Provides
 import dagger.multibindings.IntoMap
 import dagger.multibindings.StringKey
 
@@ -31,4 +37,22 @@
     @IntoMap
     @StringKey(QRCodeScannerTile.TILE_SPEC)
     fun bindQRCodeScannerTile(qrCodeScannerTile: QRCodeScannerTile): QSTileImpl<*>
+
+    companion object {
+        const val QR_CODE_SCANNER_TILE_SPEC = "qr_code_scanner"
+
+        @Provides
+        @IntoMap
+        @StringKey(QR_CODE_SCANNER_TILE_SPEC)
+        fun provideQRCodeScannerTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(QR_CODE_SCANNER_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = R.drawable.ic_qr_code_scanner,
+                        labelRes = R.string.qr_code_scanner_title,
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
index ffbd06f..d715f42 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
@@ -23,10 +23,10 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.qs.dagger.QSScope;
+import com.android.systemui.res.R;
 import com.android.systemui.retail.domain.interactor.RetailModeInteractor;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.ViewController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
index 77a5ce3..dc83201 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java
@@ -26,9 +26,9 @@
 
 import androidx.core.widget.NestedScrollView;
 
-import com.android.systemui.res.R;
 import com.android.systemui.qs.touch.OverScroll;
 import com.android.systemui.qs.touch.SwipeDetector;
+import com.android.systemui.res.R;
 
 /**
  * Quick setting scroll view containing the brightness slider and the QS tiles.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 6c32ed3..168be40 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -25,8 +25,8 @@
 
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.FontSizeUtils;
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.res.R;
 
 /**
  * Version of QSPanel that only shows N Quick Tiles in the QS Header.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java
index a1b617f..7cb950b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java
@@ -24,11 +24,11 @@
 import com.android.systemui.flags.Flags;
 import com.android.systemui.util.settings.GlobalSettings;
 
-import javax.inject.Named;
-
 import dagger.Module;
 import dagger.Provides;
 
+import javax.inject.Named;
+
 @Module
 public interface QSFlagsModule {
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
index 83b6f0d..c302ee2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/QSTileServiceWrapper.java
@@ -21,7 +21,6 @@
 
 import androidx.annotation.NonNull;
 
-
 public class QSTileServiceWrapper {
     private static final String TAG = "IQSTileServiceWrapper";
 
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 3ee4a1b..f8bf0a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -31,11 +31,9 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
 import com.android.systemui.qs.pipeline.data.repository.CustomTileAddedRepository;
 import com.android.systemui.settings.UserTracker;
-import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import java.util.List;
 import java.util.Objects;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index c3744df..8278c79 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -46,7 +46,7 @@
 import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/TileSpec.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/TileSpec.kt
index 4a8e33a..2e52845 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/TileSpec.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/TileSpec.kt
@@ -60,6 +60,7 @@
 
     companion object {
         /** Create a [TileSpec] from the string [spec]. */
+        @JvmStatic
         fun create(spec: String): TileSpec {
             return if (TextUtils.isEmpty(spec)) {
                 Invalid
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index bdcbac0..b929c43 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -25,13 +25,13 @@
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.external.CustomTile;
 
+import dagger.Lazy;
+
 import java.util.Map;
 
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import dagger.Lazy;
-
 /**
  * A factory that creates Quick Settings tiles based on a tileSpec
  *
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
index 736f035..6502a42 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CameraToggleTile.java
@@ -31,7 +31,6 @@
 import androidx.annotation.NonNull;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -40,6 +39,7 @@
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
index c15289f..1a8530f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataUsageDetailView.java
@@ -28,8 +28,8 @@
 import com.android.settingslib.Utils;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.FontSizeUtils;
-import com.android.systemui.res.R;
 import com.android.systemui.qs.DataUsageGraph;
+import com.android.systemui.res.R;
 
 import java.text.DecimalFormat;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 9fab51f..f022981 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -29,7 +29,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -40,6 +39,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.FlashlightController;
 
 import javax.inject.Inject;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 9ee417e..4d0404d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -33,7 +33,6 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -44,6 +43,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.HotspotController;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index 24b2d8a..0f260e3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -41,7 +41,6 @@
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.net.DataUsageController;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -53,6 +52,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.qs.tiles.dialog.InternetDialogManager;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.connectivity.AccessPointController;
 import com.android.systemui.statusbar.connectivity.IconState;
 import com.android.systemui.statusbar.connectivity.MobileDataIndicators;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 9ddcf295..b3f0d8b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -29,7 +29,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -41,6 +40,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
index 92338cb..36f3dc7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/MicrophoneToggleTile.java
@@ -31,7 +31,6 @@
 import androidx.annotation.NonNull;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -40,6 +39,7 @@
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index a239c28..d650f73 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -34,7 +34,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.res.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -46,6 +45,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 
 import javax.inject.Inject;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
index 7e0fa07..a1ea46d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java
@@ -36,7 +36,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.NightDisplayListenerModule;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -48,6 +47,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.LocationController;
 
 import java.text.DateFormat;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
index b9d902a..76ada10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java
@@ -30,7 +30,6 @@
 
 import com.android.internal.R;
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R.drawable;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -42,6 +41,7 @@
 import com.android.systemui.qs.ReduceBrightColorsController;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R.drawable;
 
 import javax.inject.Inject;
 import javax.inject.Named;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
index 300cc56..d92873ada 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java
@@ -31,7 +31,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -42,6 +41,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.LocationController;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index 7a9384a..abc4812 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -32,7 +32,6 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -43,6 +42,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 
 import javax.inject.Inject;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
index c1986fa..22146ce 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
 package com.android.systemui.qs.ui.viewmodel
 
 import androidx.lifecycle.LifecycleOwner
@@ -30,7 +32,7 @@
 import com.android.systemui.qs.FooterActionsController
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
 import com.android.systemui.qs.ui.adapter.QSSceneAdapter
-import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.domain.interactor.SceneBackInteractor
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
 import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
@@ -42,6 +44,8 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
 /** Models UI state and handles user input for the quick settings scene. */
@@ -57,21 +61,30 @@
     val notifications: NotificationsPlaceholderViewModel,
     private val footerActionsViewModelFactory: FooterActionsViewModel.Factory,
     private val footerActionsController: FooterActionsController,
-    sceneInteractor: SceneInteractor,
+    sceneBackInteractor: SceneBackInteractor,
 ) {
-    @OptIn(ExperimentalCoroutinesApi::class)
+    private val backScene: StateFlow<SceneKey> =
+        sceneBackInteractor.backScene
+            .filter { it != Scenes.QuickSettings }
+            .map { it ?: Scenes.Shade }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = Scenes.Shade,
+            )
+
     val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
         combine(
                 deviceEntryInteractor.isUnlocked,
                 deviceEntryInteractor.canSwipeToEnter,
                 qsSceneAdapter.isCustomizing,
-                sceneInteractor.previousScene(ignored = Scenes.QuickSettings),
-            ) { isUnlocked, canSwipeToDismiss, isCustomizing, previousScene ->
+                backScene,
+            ) { isUnlocked, canSwipeToDismiss, isCustomizing, backScene ->
                 destinationScenes(
                     isUnlocked,
                     canSwipeToDismiss,
                     isCustomizing,
-                    previousScene,
+                    backScene,
                 )
             }
             .stateIn(
@@ -82,8 +95,7 @@
                         isUnlocked = deviceEntryInteractor.isUnlocked.value,
                         canSwipeToDismiss = deviceEntryInteractor.canSwipeToEnter.value,
                         isCustomizing = qsSceneAdapter.isCustomizing.value,
-                        previousScene = sceneInteractor
-                                .previousScene(ignored = Scenes.QuickSettings).value,
+                        backScene = backScene.value,
                     ),
             )
 
@@ -91,7 +103,7 @@
         isUnlocked: Boolean,
         canSwipeToDismiss: Boolean?,
         isCustomizing: Boolean,
-        previousScene: SceneKey?
+        backScene: SceneKey?,
     ): Map<UserAction, UserActionResult> {
         val upBottomEdge =
             when {
@@ -108,13 +120,15 @@
                 // TODO(b/330200163) Add an Up from Bottom to be able to collapse the shade
                 // while customizing
             } else {
-                this[Back] = UserActionResult(previousScene ?: Scenes.Shade)
-                this[Swipe(SwipeDirection.Up)] = UserActionResult(previousScene ?: Scenes.Shade)
-                this[
+                put(Back, UserActionResult(backScene ?: Scenes.Shade))
+                put(Swipe(SwipeDirection.Up), UserActionResult(backScene ?: Scenes.Shade))
+                put(
                     Swipe(
                         fromSource = Edge.Bottom,
                         direction = SwipeDirection.Up,
-                    )] = UserActionResult(upBottomEdge)
+                    ),
+                    UserActionResult(upBottomEdge),
+                )
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 520331a..b92e8eb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -253,8 +253,21 @@
 
         @Override
         public void onStatusBarTrackpadEvent(MotionEvent event) {
-            verifyCallerAndClearCallingIdentityPostMain("onStatusBarTrackpadEvent", () ->
-                    mShadeViewControllerLazy.get().handleExternalTouch(event));
+            verifyCallerAndClearCallingIdentityPostMain("onStatusBarTrackpadEvent", () -> {
+                if (SceneContainerFlag.isEnabled()) {
+                    int action = event.getActionMasked();
+                    if (action == ACTION_DOWN) {
+                        mSceneInteractor.get().onRemoteUserInteractionStarted(
+                                "trackpad swipe");
+                    } else if (action == ACTION_UP) {
+                        mSceneInteractor.get().changeScene(
+                                Scenes.Shade, "short trackpad swipe");
+                    }
+                    mStatusBarWinController.getWindowRootView().dispatchTouchEvent(event);
+                } else {
+                    mShadeViewControllerLazy.get().handleExternalTouch(event);
+                }
+            });
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt
index d67cf4d..26af9a7 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueModule.kt
@@ -16,10 +16,16 @@
 
 package com.android.systemui.recordissue
 
+import com.android.systemui.qs.QsEventLogger
+import com.android.systemui.qs.pipeline.shared.TileSpec
 import com.android.systemui.qs.tileimpl.QSTileImpl
 import com.android.systemui.qs.tiles.RecordIssueTile
+import com.android.systemui.qs.tiles.viewmodel.QSTileConfig
+import com.android.systemui.qs.tiles.viewmodel.QSTileUIConfig
+import com.android.systemui.res.R
 import dagger.Binds
 import dagger.Module
+import dagger.Provides
 import dagger.multibindings.IntoMap
 import dagger.multibindings.StringKey
 
@@ -30,4 +36,23 @@
     @IntoMap
     @StringKey(RecordIssueTile.TILE_SPEC)
     fun bindRecordIssueTile(recordIssueTile: RecordIssueTile): QSTileImpl<*>
+
+    companion object {
+
+        const val RECORD_ISSUE_TILE_SPEC = "record_issue"
+
+        @Provides
+        @IntoMap
+        @StringKey(RECORD_ISSUE_TILE_SPEC)
+        fun provideRecordIssueTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(RECORD_ISSUE_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = R.drawable.qs_record_issue_icon_off,
+                        labelRes = R.string.qs_record_issue_label
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index 8277c73..2a73b53 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -47,6 +47,12 @@
                     Scenes.Shade,
                 ),
             initialSceneKey = Scenes.Gone,
+            navigationDistances =
+                mapOf(
+                    Scenes.Gone to 0,
+                    Scenes.Shade to 1,
+                    Scenes.QuickSettings to 2,
+                ),
         )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index 69f9443..cd1b965 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -73,6 +73,15 @@
                         Scenes.Shade,
                     ),
                 initialSceneKey = Scenes.Lockscreen,
+                navigationDistances =
+                    mapOf(
+                        Scenes.Gone to 0,
+                        Scenes.Lockscreen to 0,
+                        Scenes.Communal to 1,
+                        Scenes.Shade to 2,
+                        Scenes.QuickSettings to 3,
+                        Scenes.Bouncer to 4,
+                    ),
             )
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
index d202c24..b918277 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
@@ -47,6 +47,11 @@
                     Scenes.Bouncer,
                 ),
             initialSceneKey = Scenes.Lockscreen,
+            mapOf(
+                Scenes.Gone to 0,
+                Scenes.Lockscreen to 0,
+                Scenes.Bouncer to 1,
+            )
         )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
index 3082eb9..994b012 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/data/repository/SceneContainerRepository.kt
@@ -24,8 +24,6 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.SceneDataSource
-import com.android.systemui.util.kotlin.WithPrev
-import com.android.systemui.util.kotlin.pairwise
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -36,7 +34,6 @@
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
 /** Source of truth for scene framework application state. */
@@ -47,32 +44,7 @@
     private val config: SceneContainerConfig,
     private val dataSource: SceneDataSource,
 ) {
-    private val previousAndCurrentScene: StateFlow<WithPrev<SceneKey?, SceneKey>> =
-        dataSource.currentScene
-            .pairwise()
-            .stateIn(
-                scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
-                initialValue = WithPrev(null, dataSource.currentScene.value),
-            )
-
-    val currentScene: StateFlow<SceneKey> =
-        previousAndCurrentScene
-            .map { it.newValue }
-            .stateIn(
-                scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
-                initialValue = previousAndCurrentScene.value.newValue,
-            )
-
-    val previousScene: StateFlow<SceneKey?> =
-        previousAndCurrentScene
-            .map { it.previousValue }
-            .stateIn(
-                scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
-                initialValue = previousAndCurrentScene.value.previousValue,
-            )
+    val currentScene: StateFlow<SceneKey> = dataSource.currentScene
 
     private val _isVisible = MutableStateFlow(true)
     val isVisible: StateFlow<Boolean> = _isVisible.asStateFlow()
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
new file mode 100644
index 0000000..f66d08f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneBackInteractor.kt
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.scene.domain.interactor
+
+import com.android.compose.animation.scene.SceneKey
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.scene.shared.logger.SceneLogger
+import com.android.systemui.scene.shared.model.SceneContainerConfig
+import java.util.Stack
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+@SysUISingleton
+class SceneBackInteractor
+@Inject
+constructor(
+    private val logger: SceneLogger,
+    private val sceneContainerConfig: SceneContainerConfig,
+) {
+    private val _backScene = MutableStateFlow<SceneKey?>(null)
+    /**
+     * The scene to navigate to when the user triggers back navigation.
+     *
+     * This is meant for scene implementations to consult with when they implement their destination
+     * scene flow.
+     *
+     * Note that this flow could emit any scene from the [SceneContainerConfig] and that it's an
+     * illegal state to have scene implementation map to itself in its destination scene flow. Thus,
+     * scene implementations might wish to filter their own scene key out before using this.
+     */
+    val backScene: StateFlow<SceneKey?> = _backScene.asStateFlow()
+
+    private val backStack = Stack<SceneKey>()
+
+    fun onSceneChange(from: SceneKey, to: SceneKey) {
+        check(from != to) { "from == to, from=${from.debugName}, to=${to.debugName}" }
+        when (stackOperation(from, to)) {
+            Clear -> {
+                backStack.clear()
+            }
+            Push -> {
+                backStack.push(from)
+            }
+            Pop -> {
+                check(backStack.isNotEmpty()) { "Cannot pop ${from.debugName} when stack is empty" }
+                val popped = backStack.pop()
+                check(to == popped) {
+                    "Expected to pop ${to.debugName} but instead popped ${popped.debugName}"
+                }
+            }
+        }
+
+        logger.logSceneBackStack(backStack)
+        _backScene.value = peek()
+    }
+
+    private fun stackOperation(from: SceneKey, to: SceneKey): StackOperation {
+        val fromDistance =
+            checkNotNull(sceneContainerConfig.navigationDistances[from]) {
+                "No distance mapping for scene \"${from.debugName}\"!"
+            }
+        val toDistance =
+            checkNotNull(sceneContainerConfig.navigationDistances[to]) {
+                "No distance mapping for scene \"${to.debugName}\"!"
+            }
+
+        return when {
+            toDistance == 0 -> Clear
+            toDistance > fromDistance -> Push
+            toDistance < fromDistance -> Pop
+            else ->
+                error(
+                    "No mapping when from=${from.debugName} (distance=$fromDistance)," +
+                        " to=${to.debugName} (distance=$toDistance)!"
+                )
+        }
+    }
+
+    private fun peek(): SceneKey? {
+        return if (backStack.isNotEmpty()) {
+            backStack.peek()
+        } else {
+            null
+        }
+    }
+
+    private sealed interface StackOperation
+    private data object Clear : StackOperation
+    private data object Push : StackOperation
+    private data object Pop : StackOperation
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index 8ced222..2ccd3b9 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -140,33 +140,6 @@
             )
 
     /**
-     * The previous scene (or `null` if the previous scene is the [ignored] scene).
-     *
-     * This is effectively the previous value of [currentScene] which means that all caveats, for
-     * example regarding when in a transition the current scene changes, apply.
-     *
-     * @param ignored If the previous scene is the same as [ignored], `null` is emitted. This is
-     *   designed to reduce the chances of a scene using [previousScene] naively to then set up a
-     *   user action that ends up leading to itself, which is an illegal operation that would cause
-     *   a crash.
-     */
-    fun previousScene(
-        ignored: SceneKey? = null,
-    ): StateFlow<SceneKey?> {
-        fun SceneKey?.nullifyIfIgnored(): SceneKey? {
-            return this?.takeIf { this != ignored }
-        }
-
-        return repository.previousScene
-            .map { it.nullifyIfIgnored() }
-            .stateIn(
-                scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
-                initialValue = repository.previousScene.value.nullifyIfIgnored(),
-            )
-    }
-
-    /**
      * Returns the keys of all scenes in the container.
      *
      * The scenes will be sorted in z-order such that the last one is the one that should be
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 4fc24b8..39ec12f 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -45,6 +45,7 @@
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.plugins.FalsingManager.FalsingBeliefListener
 import com.android.systemui.power.domain.interactor.PowerInteractor
+import com.android.systemui.scene.domain.interactor.SceneBackInteractor
 import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
 import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
@@ -56,6 +57,7 @@
 import com.android.systemui.statusbar.phone.CentralSurfaces
 import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
 import com.android.systemui.util.asIndenting
+import com.android.systemui.util.kotlin.pairwise
 import com.android.systemui.util.kotlin.sample
 import com.android.systemui.util.printSection
 import com.android.systemui.util.println
@@ -111,6 +113,7 @@
     private val faceUnlockInteractor: DeviceEntryFaceAuthInteractor,
     private val shadeInteractor: ShadeInteractor,
     private val uiEventLogger: UiEventLogger,
+    private val sceneBackInteractor: SceneBackInteractor,
 ) : CoreStartable {
 
     override fun start() {
@@ -124,6 +127,7 @@
             hydrateInteractionState()
             handleBouncerOverscroll()
             hydrateWindowController()
+            hydrateBackStack()
         } else {
             sceneLogger.logFrameworkEnabled(
                 isEnabled = false,
@@ -257,8 +261,7 @@
             // Track the previous scene (sans Bouncer), so that we know where to go when the device
             // is unlocked whilst on the bouncer.
             val previousScene =
-                sceneInteractor
-                    .previousScene()
+                sceneBackInteractor.backScene
                     .filterNot { it == Scenes.Bouncer }
                     .stateIn(this, SharingStarted.Eagerly, initialValue = null)
             deviceUnlockedInteractor.deviceUnlockStatus
@@ -581,4 +584,12 @@
             loggingReason = loggingReason,
         )
     }
+
+    private fun hydrateBackStack() {
+        applicationScope.launch {
+            sceneInteractor.currentScene.pairwise().collect { (from, to) ->
+                sceneBackInteractor.onSceneChange(from = from, to = to)
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
index f44779a..5ebdd86 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt
@@ -20,6 +20,7 @@
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.core.LogLevel
 import com.android.systemui.log.dagger.SceneFrameworkLog
+import java.util.Stack
 import javax.inject.Inject
 
 class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer: LogBuffer) {
@@ -102,7 +103,7 @@
             tag = TAG,
             level = LogLevel.INFO,
             messageInitializer = { str1 = reason },
-            messagePrinter = { "remote user interaction started, reason: $str3" },
+            messagePrinter = { "remote user interaction started, reason: $str1" },
         )
     }
 
@@ -115,6 +116,15 @@
         )
     }
 
+    fun logSceneBackStack(backStack: Stack<SceneKey>) {
+        logBuffer.log(
+            tag = TAG,
+            level = LogLevel.INFO,
+            messageInitializer = { str1 = backStack.joinToString(", ") { it.debugName } },
+            messagePrinter = { "back stack: $str1" },
+        )
+    }
+
     companion object {
         private const val TAG = "SceneFramework"
     }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneContainerConfig.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneContainerConfig.kt
index 53cdaaa..0a30c31 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneContainerConfig.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneContainerConfig.kt
@@ -25,6 +25,9 @@
      * The keys to all scenes in the container, sorted by z-order such that the last one renders on
      * top of all previous ones. Scene keys within the same container must not repeat but it's okay
      * to have the same scene keys in different containers.
+     *
+     * Note that this doesn't control how back navigation works; for that, we have
+     * [navigationDistances].
      */
     val sceneKeys: List<SceneKey>,
 
@@ -33,6 +36,24 @@
      * before taking any application state in to account.
      */
     val initialSceneKey: SceneKey,
+
+    /**
+     * Navigation distance of each scene.
+     *
+     * The navigation distance is a measure of how many non-back user action "steps" away from the
+     * starting scene, each scene is.
+     *
+     * The framework uses these to help scene implementations decide which scene to go back to when
+     * the user attempts to navigate back on them, if they need that.
+     *
+     * In general, the more non-back user actions are needed to get to a scene, the greater that
+     * scene's distance should be. Navigating "back" then goes from scenes with a higher distance to
+     * scenes with a lower distance.
+     *
+     * Note that this is not the z-order of rendering; that's determined by the order of declaration
+     * of scenes in the [sceneKeys] list.
+     */
+    val navigationDistances: Map<SceneKey, Int>
 ) {
     init {
         check(sceneKeys.isNotEmpty()) { "A container must have at least one scene key." }
@@ -40,5 +61,9 @@
         check(sceneKeys.contains(initialSceneKey)) {
             "The initial key \"$initialSceneKey\" is not present in this container."
         }
+
+        check(navigationDistances.keys == sceneKeys.toSet()) {
+            "Scene keys and distance map must match."
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/OverlayActionChip.java b/packages/SystemUI/src/com/android/systemui/screenshot/OverlayActionChip.java
index 30f5e8b..9e68c48 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/OverlayActionChip.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/OverlayActionChip.java
@@ -32,7 +32,6 @@
 
 import com.android.systemui.res.R;
 
-
 /**
  * View for a chip with an icon and text.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 501a4a7..494fc9b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -97,7 +97,6 @@
 
 import javax.inject.Provider;
 
-
 /**
  * Controls the state and flow for screenshots.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
index ef58b9d..f8b22a6 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SmartActionsReceiver.java
@@ -31,7 +31,6 @@
 
 import javax.inject.Inject;
 
-
 /**
  * Executes the smart action tapped by the user in the notification.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java
index c89b476..3bca4e4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsService.java
@@ -38,9 +38,9 @@
 import androidx.annotation.Nullable;
 
 import com.android.internal.statusbar.IAppClipsService;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Application;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.res.R;
 import com.android.wm.shell.bubbles.Bubbles;
 
 import java.util.Optional;
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 a31b301..48449b3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivity.java
@@ -48,13 +48,13 @@
 import com.android.internal.infra.ServiceConnector;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.statusbar.IAppClipsService;
-import com.android.systemui.res.R;
 import com.android.systemui.broadcast.BroadcastSender;
 import com.android.systemui.dagger.qualifiers.Application;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.notetask.NoteTaskController;
 import com.android.systemui.notetask.NoteTaskEntryPoint;
+import com.android.systemui.res.R;
 
 import java.util.concurrent.Executor;
 
diff --git a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
index 20bd7c6..49f3cfc 100644
--- a/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/scrim/ScrimView.java
@@ -44,7 +44,6 @@
 
 import java.util.concurrent.Executor;
 
-
 /**
  * A view which can draw a scrim.  This view maybe be used in multiple windows running on different
  * threads, but is controlled by {@link com.android.systemui.statusbar.phone.ScrimController} so we
diff --git a/packages/SystemUI/src/com/android/systemui/settings/MultiUserUtilsModule.java b/packages/SystemUI/src/com/android/systemui/settings/MultiUserUtilsModule.java
index fd807db..05f19ef 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/MultiUserUtilsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/MultiUserUtilsModule.java
@@ -36,11 +36,11 @@
 import dagger.multibindings.ClassKey;
 import dagger.multibindings.IntoMap;
 
-import javax.inject.Provider;
-
 import kotlinx.coroutines.CoroutineDispatcher;
 import kotlinx.coroutines.CoroutineScope;
 
+import javax.inject.Provider;
+
 /**
  * Dagger Module for classes found within the com.android.systemui.settings package.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
index a5a5474..ff5fdc6 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.shade
 
 import android.content.Context
+import android.graphics.Rect
 import android.os.PowerManager
 import android.os.SystemClock
 import android.view.GestureDetector
@@ -215,6 +216,32 @@
                 R.dimen.communal_right_edge_swipe_region_width
             )
 
+        val topEdgeSwipeRegionWidth =
+            containerView.resources.getDimensionPixelSize(
+                R.dimen.communal_top_edge_swipe_region_height
+            )
+        val bottomEdgeSwipeRegionWidth =
+            containerView.resources.getDimensionPixelSize(
+                R.dimen.communal_bottom_edge_swipe_region_height
+            )
+
+        // BouncerSwipeTouchHandler has a larger gesture area than we want, set an exclusion area so
+        // the gesture area doesn't overlap with widgets.
+        // TODO(b/323035776): adjust gesture areaa for portrait mode
+        containerView.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.CREATED) {
+                val exclusionRect =
+                    Rect(
+                        0,
+                        topEdgeSwipeRegionWidth,
+                        containerView.right,
+                        containerView.bottom - bottomEdgeSwipeRegionWidth
+                    )
+
+                containerView.systemGestureExclusionRects = listOf(exclusionRect)
+            }
+        }
+
         collectFlow(
             containerView,
             keyguardTransitionInteractor.isFinishedInStateWhere(KeyguardState::isBouncerState),
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index aa915e3..67211b1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -242,6 +242,9 @@
 
 import kotlin.Unit;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+import kotlinx.coroutines.flow.Flow;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -251,9 +254,6 @@
 import javax.inject.Inject;
 import javax.inject.Provider;
 
-import kotlinx.coroutines.CoroutineDispatcher;
-import kotlinx.coroutines.flow.Flow;
-
 @SysUISingleton
 public final class NotificationPanelViewController implements ShadeSurface, Dumpable {
 
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index df9c57c..37da114 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -59,10 +59,11 @@
 import com.android.systemui.shade.carrier.ShadeCarrierGroup
 import com.android.systemui.shade.carrier.ShadeCarrierGroupController
 import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
-import com.android.systemui.statusbar.phone.StatusBarIconController
 import com.android.systemui.statusbar.phone.StatusBarLocation
 import com.android.systemui.statusbar.phone.StatusIconContainer
 import com.android.systemui.statusbar.phone.StatusOverlayHoverListenerFactory
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController
+import com.android.systemui.statusbar.phone.ui.TintedIconManager
 import com.android.systemui.statusbar.policy.Clock
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.NextAlarmController
@@ -88,7 +89,7 @@
 constructor(
     @Named(SHADE_HEADER) private val header: MotionLayout,
     private val statusBarIconController: StatusBarIconController,
-    private val tintedIconManagerFactory: StatusBarIconController.TintedIconManager.Factory,
+    private val tintedIconManagerFactory: TintedIconManager.Factory,
     private val privacyIconsController: HeaderPrivacyIconsController,
     private val insetsProvider: StatusBarContentInsetsProvider,
     private val configurationController: ConfigurationController,
@@ -127,7 +128,7 @@
 
     var shadeCollapseAction: Runnable? = null
 
-    private lateinit var iconManager: StatusBarIconController.TintedIconManager
+    private lateinit var iconManager: TintedIconManager
     private lateinit var carrierIconSlots: List<String>
     private lateinit var mShadeCarrierGroupController: ShadeCarrierGroupController
 
@@ -303,10 +304,18 @@
         // battery settings same as in QS icons
         batteryMeterViewController.ignoreTunerUpdates()
 
+        val fgColor =
+            Utils.getColorAttrDefaultColor(header.context, android.R.attr.textColorPrimary)
+        val bgColor =
+            Utils.getColorAttrDefaultColor(header.context, android.R.attr.textColorPrimaryInverse)
+
         iconManager = tintedIconManagerFactory.create(iconContainer, StatusBarLocation.QS)
-        iconManager.setTint(
-            Utils.getColorAttrDefaultColor(header.context, android.R.attr.textColorPrimary),
-            Utils.getColorAttrDefaultColor(header.context, android.R.attr.textColorPrimaryInverse),
+        iconManager.setTint(fgColor, bgColor)
+
+        batteryIcon.updateColors(
+            fgColor /* foreground */,
+            bgColor /* background */,
+            fgColor /* single tone (current default) */
         )
 
         carrierIconSlots =
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
index 4ec0b23..9dc19b1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewController.kt
@@ -177,8 +177,7 @@
 @Deprecated("This interface should not be used in scene container.")
 interface ShadeViewStateProvider {
     /** Returns the expanded height of the panel view. */
-    @Deprecated("deprecated by migrate_keyguard_status_bar_view flag")
-    val panelViewExpandedHeight: Float
+    @Deprecated("deprecated by SceneContainerFlag.isEnabled") val panelViewExpandedHeight: Float
 
     /**
      * Returns true if heads up should be visible.
@@ -189,6 +188,5 @@
     @Deprecated("deprecated in Flexiglass.") fun shouldHeadsUpBeVisible(): Boolean
 
     /** Return the fraction of the shade that's expanded, when in lockscreen. */
-    @Deprecated("deprecated by migrate_keyguard_status_bar_view flag")
-    val lockscreenShadeDragProgress: Float
+    @Deprecated("deprecated by SceneContainerFlag.isEnabled") val lockscreenShadeDragProgress: Float
 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
index c429329..4b6dd8d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/carrier/ShadeCarrierGroupController.java
@@ -39,11 +39,11 @@
 import com.android.keyguard.CarrierTextManager;
 import com.android.settingslib.AccessibilityContentDescriptions;
 import com.android.settingslib.mobile.TelephonyIcons;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.connectivity.MobileDataIndicators;
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.connectivity.SignalCallback;
@@ -199,7 +199,7 @@
 
         for (int i = 0; i < SIM_SLOTS; i++) {
             mInfos[i] = new CellSignalState(
-                    true,
+                    false,
                     R.drawable.ic_shade_no_calling_sms,
                     context.getText(AccessibilityContentDescriptions.NO_CALLING).toString(),
                     "",
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/ui/binder/SmartspaceViewBinder.kt b/packages/SystemUI/src/com/android/systemui/smartspace/ui/binder/SmartspaceViewBinder.kt
new file mode 100644
index 0000000..6c3d7df
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/ui/binder/SmartspaceViewBinder.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.smartspace.ui.binder
+
+import android.view.View
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
+import com.android.systemui.smartspace.ui.viewmodel.SmartspaceViewModel
+import kotlinx.coroutines.launch
+
+/** Binds the view and view-model for the smartspace. */
+object SmartspaceViewBinder {
+
+    /** Binds the view and view-model for the smartspace. */
+    fun bind(
+        smartspaceView: SmartspaceView,
+        viewModel: SmartspaceViewModel,
+    ) {
+        val view = smartspaceView as View
+        view.repeatWhenAttached {
+            repeatOnLifecycle(Lifecycle.State.CREATED) {
+                launch {
+                    // Observe screen on/off changes
+                    viewModel.isAwake.collect { isAwake -> smartspaceView.setScreenOn(isAwake) }
+                }
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/ui/viewmodel/SmartspaceViewModel.kt b/packages/SystemUI/src/com/android/systemui/smartspace/ui/viewmodel/SmartspaceViewModel.kt
new file mode 100644
index 0000000..4177383
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/ui/viewmodel/SmartspaceViewModel.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.smartspace.ui.viewmodel
+
+import com.android.systemui.power.domain.interactor.PowerInteractor
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filter
+
+class SmartspaceViewModel
+@AssistedInject
+constructor(
+    powerInteractor: PowerInteractor,
+    @Assisted val surfaceName: String,
+) {
+
+    /** Screen on/off state */
+    val isAwake: Flow<Boolean> =
+        powerInteractor.isAwake.filter { surfaceName != SURFACE_WEATHER_VIEW }
+
+    @AssistedFactory
+    interface Factory {
+        fun create(surfaceName: String): SmartspaceViewModel
+    }
+
+    companion object {
+        const val SURFACE_DATE_VIEW = "date_view"
+        const val SURFACE_WEATHER_VIEW = "weather_view"
+        const val SURFACE_GENERAL_VIEW = "general_view"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
index 8d9fab1..d278b3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/HeadsUpStatusBarView.java
@@ -26,14 +26,13 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.keyguard.AlphaOptimizedLinearLayout;
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry.OnSensitivityChangedListener;
 
 import java.util.ArrayList;
 
-
 /**
  * The view in the statusBar that contains part of the heads-up information
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 09985f8..7983db1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -21,6 +21,7 @@
 import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_MANAGEMENT_DISCLOSURE;
 import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_NAMED_MANAGEMENT_DISCLOSURE;
 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT;
 import static android.hardware.biometrics.BiometricSourceType.FACE;
 import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
 import static android.view.View.GONE;
@@ -60,7 +61,6 @@
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.hardware.biometrics.BiometricSourceType;
-import android.hardware.face.FaceManager;
 import android.os.BatteryManager;
 import android.os.Handler;
 import android.os.Looper;
@@ -1404,7 +1404,7 @@
                 mKeyguardLogger.logBiometricMessage("KIC suppressingFaceError", msgId, errString);
                 return;
             }
-            if (msgId == FaceManager.FACE_ERROR_TIMEOUT) {
+            if (msgId == FACE_ERROR_TIMEOUT) {
                 handleFaceAuthTimeoutError(deferredFaceMessage);
             } else if (mIndicationHelper.isFaceLockoutErrorMsg(msgId)) {
                 handleFaceLockoutError(errString);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
index ac510fe..37989f5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
@@ -190,12 +190,12 @@
     private companion object {
         // From which percentage we should start the gradient reveal width
         // E.g. if 0 - starts with 0px width, 0.6f - starts with 60% width
-        private const val GRADIENT_START_BOUNDS_PERCENTAGE: Float = 1f
+        private const val GRADIENT_START_BOUNDS_PERCENTAGE: Float = 0.95f
 
         // When to start changing alpha color of the gradient scrim
         // E.g. if 0.6f - starts fading the gradient away at 60% and becomes completely
         // transparent at 100%
-        private const val REVEAL_GRADIENT_END_COLOR_ALPHA_START_PERCENTAGE: Float = 1f
+        private const val REVEAL_GRADIENT_END_COLOR_ALPHA_START_PERCENTAGE: Float = 0.95f
 
         // When to finish displaying start color fill that reveals the content
         // E.g. if 0.6f - the content won't be visible at 0% and it will gradually
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 0091bc5..854ef92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -33,7 +33,6 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityOptions;
 import android.app.KeyguardManager;
-import android.app.Notification;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -65,7 +64,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlagsClassic;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.recents.OverviewProxyService;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameViewController.java
index 6e7d8f4..0d789c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameViewController.java
@@ -34,10 +34,10 @@
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.kotlin.JavaAdapter;
 
-import javax.inject.Inject;
-
 import kotlinx.coroutines.Job;
 
+import javax.inject.Inject;
+
 /** Controller for {@link OperatorNameView}. */
 public class OperatorNameViewController extends ViewController<OperatorNameView> {
     private static final String KEY_SHOW_OPERATOR_NAME = "show_operator_name";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java
index 1638780..5391992 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java
@@ -32,7 +32,6 @@
 
 import javax.inject.Inject;
 
-
 /**
  * Implements network listeners and forwards the calls along onto other listeners but on
  * the current or specified Looper.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
index 7a7cb7d..c7952b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityModule.kt
@@ -95,6 +95,9 @@
         const val AIRPLANE_MODE_TILE_SPEC = "airplane"
         const val DATA_SAVER_TILE_SPEC = "saver"
         const val INTERNET_TILE_SPEC = "internet"
+        const val HOTSPOT_TILE_SPEC = "hotspot"
+        const val CAST_TILE_SPEC = "cast"
+        const val BLUETOOTH_TILE_SPEC = "bt"
 
         /** Inject InternetTile or InternetTileNewImpl into tileMap in QSModule */
         @Provides
@@ -204,5 +207,47 @@
                 stateInteractor,
                 mapper,
             )
+
+        @Provides
+        @IntoMap
+        @StringKey(HOTSPOT_TILE_SPEC)
+        fun provideHotspotTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(HOTSPOT_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = R.drawable.ic_hotspot,
+                        labelRes = R.string.quick_settings_hotspot_label,
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
+
+        @Provides
+        @IntoMap
+        @StringKey(CAST_TILE_SPEC)
+        fun provideCastTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(CAST_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = R.drawable.ic_cast,
+                        labelRes = R.string.quick_settings_cast_title,
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
+
+        @Provides
+        @IntoMap
+        @StringKey(BLUETOOTH_TILE_SPEC)
+        fun provideBluetoothTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(BLUETOOTH_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = R.drawable.qs_bluetooth_icon_off,
+                        labelRes = R.string.quick_settings_bluetooth_label,
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalController.java
index 7e8f04e..2d2ee4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalController.java
@@ -29,7 +29,6 @@
 import java.util.BitSet;
 import java.util.List;
 
-
 /**
  * Common base class for handling signal for both wifi and mobile data.
  *
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java
index 08defcc..0e572be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java
@@ -34,8 +34,8 @@
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.wifi.WifiStatusTracker;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.res.R;
 
 import java.io.PrintWriter;
 import java.util.BitSet;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 594c191..8a53e0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -55,10 +55,10 @@
 import com.android.systemui.statusbar.phone.CentralSurfacesImpl;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
-import com.android.systemui.statusbar.phone.StatusBarIconList;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconList;
 import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconControllerImpl;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import dagger.Binds;
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 c29a64e..446a0d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -40,6 +40,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor
 import com.android.settingslib.Utils
 import com.android.systemui.Dumpable
+import com.android.systemui.Flags.smartspaceLockscreenViewmodel
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
@@ -60,6 +61,8 @@
 import com.android.systemui.shared.regionsampling.RegionSampler
 import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DATE_SMARTSPACE_DATA_PLUGIN
 import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN
+import com.android.systemui.smartspace.ui.binder.SmartspaceViewBinder
+import com.android.systemui.smartspace.ui.viewmodel.SmartspaceViewModel
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
@@ -98,6 +101,7 @@
         private val bypassController: KeyguardBypassController,
         private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
         private val wakefulnessLifecycle: WakefulnessLifecycle,
+        private val smartspaceViewModelFactory: SmartspaceViewModel.Factory,
         private val dumpManager: DumpManager,
         private val execution: Execution,
         @Main private val uiExecutor: Executor,
@@ -333,7 +337,12 @@
             throw RuntimeException("Cannot build date view when not decoupled")
         }
 
-        val view = buildView(parent, datePlugin)
+        val view =
+            buildView(
+                surfaceName = SmartspaceViewModel.SURFACE_DATE_VIEW,
+                parent = parent,
+                plugin = datePlugin
+            )
         connectSession()
 
         return view
@@ -352,7 +361,12 @@
             throw RuntimeException("Cannot build weather view when not decoupled")
         }
 
-        val view = buildView(parent, weatherPlugin)
+        val view =
+            buildView(
+                surfaceName = SmartspaceViewModel.SURFACE_WEATHER_VIEW,
+                parent = parent,
+                plugin = weatherPlugin
+            )
         connectSession()
 
         return view
@@ -368,16 +382,23 @@
             throw RuntimeException("Cannot build view when not enabled")
         }
 
-        val view = buildView(parent, plugin, configPlugin)
+        val view =
+            buildView(
+                surfaceName = SmartspaceViewModel.SURFACE_GENERAL_VIEW,
+                parent = parent,
+                plugin = plugin,
+                configPlugin = configPlugin
+            )
         connectSession()
 
         return view
     }
 
     private fun buildView(
-            parent: ViewGroup,
-            plugin: BcSmartspaceDataPlugin?,
-            configPlugin: BcSmartspaceConfigPlugin? = null
+        surfaceName: String,
+        parent: ViewGroup,
+        plugin: BcSmartspaceDataPlugin?,
+        configPlugin: BcSmartspaceConfigPlugin? = null
     ): View? {
         if (plugin == null) {
             return null
@@ -424,6 +445,14 @@
         return (ssView as View).apply {
             setTag(R.id.tag_smartspace_view, Any())
             addOnAttachStateChangeListener(stateChangeListener)
+
+            if (smartspaceLockscreenViewmodel()) {
+                val viewModel = smartspaceViewModelFactory.create(surfaceName)
+                SmartspaceViewBinder.bind(
+                    smartspaceView = ssView,
+                    viewModel = viewModel,
+                )
+            }
         }
     }
 
@@ -466,7 +495,9 @@
         configurationController.addCallback(configChangeListener)
         statusBarStateController.addCallback(statusBarStateListener)
         bypassController.registerOnBypassStateChangedListener(bypassStateChangedListener)
-        wakefulnessLifecycle.addObserver(wakefulnessLifecycleObserver)
+        if (!smartspaceLockscreenViewmodel()) {
+            wakefulnessLifecycle.addObserver(wakefulnessLifecycleObserver)
+        }
 
         datePlugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
         weatherPlugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) }
@@ -509,7 +540,9 @@
         configurationController.removeCallback(configChangeListener)
         statusBarStateController.removeCallback(statusBarStateListener)
         bypassController.unregisterOnBypassStateChangedListener(bypassStateChangedListener)
-        wakefulnessLifecycle.removeObserver(wakefulnessLifecycleObserver)
+        if (!smartspaceLockscreenViewmodel()) {
+            wakefulnessLifecycle.removeObserver(wakefulnessLifecycleObserver)
+        }
         session = null
 
         datePlugin?.registerSmartspaceEventNotifier(null)
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 ad9e312..5bbd77e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -49,10 +49,10 @@
 import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.CoreStartable;
-import com.android.systemui.res.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.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 8b673c9..b397906 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -71,14 +71,14 @@
 import com.android.systemui.statusbar.notification.stack.PriorityBucket;
 import com.android.systemui.util.ListenerSet;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
 import kotlinx.coroutines.flow.MutableStateFlow;
 import kotlinx.coroutines.flow.StateFlow;
 import kotlinx.coroutines.flow.StateFlowKt;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
 /**
  * Represents a notification that the system UI knows about
  *
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
index 0c95eab..7251607 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
@@ -16,10 +16,8 @@
 
 package com.android.systemui.statusbar.notification.collection.coordinator;
 
-import android.Manifest;
 import android.app.Notification;
 import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
 import android.os.RemoteException;
 import android.service.notification.StatusBarNotification;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index e31e9c2..91bb28e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -87,16 +87,18 @@
 import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
-import javax.inject.Provider;
-
 import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
 import dagger.multibindings.ClassKey;
 import dagger.multibindings.IntoMap;
+
 import kotlin.coroutines.CoroutineContext;
+
 import kotlinx.coroutines.CoroutineScope;
 
+import javax.inject.Provider;
+
 /**
  * Dagger Module for classes found within the com.android.systemui.statusbar.notification package.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
index 2fdd2c6..6b5642a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/ui/viewbinder/StatusBarIconViewBinder.kt
@@ -35,12 +35,13 @@
     //  view-model (which, at the time of this writing, does not yet exist).
 
     suspend fun bindColor(view: StatusBarIconView, color: Flow<Int>) {
-        // Don't change the icon color if an app icon experiment is enabled.
-        if (!android.app.Flags.notificationsUseAppIcon()) {
-            color.collectTracingEach("SBIV#bindColor") { color ->
+        color.collectTracingEach("SBIV#bindColor") { color ->
+            // Don't change the icon color if an app icon experiment is enabled.
+            if (!android.app.Flags.notificationsUseAppIcon()) {
                 view.staticDrawableColor = color
-                view.setDecorColor(color)
             }
+            // Continue changing the overflow dot color
+            view.setDecorColor(color)
         }
     }
 
@@ -57,15 +58,16 @@
         iconColors: Flow<NotificationIconColors>,
         contrastColorUtil: ContrastColorUtil,
     ) {
-        // Don't change the icon color if an app icon experiment is enabled.
-        if (!android.app.Flags.notificationsUseAppIcon()) {
-            iconColors.collectTracingEach("SBIV#bindIconColors") { colors ->
+        iconColors.collectTracingEach("SBIV#bindIconColors") { colors ->
+            // Don't change the icon color if an app icon experiment is enabled.
+            if (!android.app.Flags.notificationsUseAppIcon()) {
                 val isPreL = java.lang.Boolean.TRUE == view.getTag(R.id.icon_is_pre_L)
                 val isColorized = !isPreL || NotificationUtils.isGrayscale(view, contrastColorUtil)
                 view.staticDrawableColor =
                     if (isColorized) colors.staticDrawableColor(view.viewBounds) else NO_COLOR
-                view.setDecorColor(colors.tint)
             }
+            // Continue changing the overflow dot color
+            view.setDecorColor(colors.tint)
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
index 6c63d1d..89aa3ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
@@ -33,6 +33,7 @@
 import com.android.systemui.statusbar.notification.stack.PriorityBucket;
 
 import java.util.List;
+
 /**
  * Statsd logging for notification panel.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index a317f95..c10c09c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -41,8 +41,8 @@
 
 import com.android.app.animation.Interpolators;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.AlphaOptimizedImageView;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
index 53f7d4b..60e98a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
@@ -37,8 +37,6 @@
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
-import java.util.Set;
-
 /**
  * The guts of a conversation notification that doesn't use valid shortcuts that is revealed when
  * performing a long press.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
index d3c874c..3fce9ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/SingleLineViewInflater.kt
@@ -217,8 +217,9 @@
         var currentGroup: MutableList<MessagingStyle.Message>? = null
         var currentSenderKey: CharSequence? = null
         val groups = mutableListOf<MutableList<MessagingStyle.Message>>()
-        for (i in 0 until (historicMessages.size + messages.size)) {
-            val message = if (i < historicMessages.size) historicMessages[i] else messages[i]
+        val histSize = historicMessages.size
+        for (i in 0 until (histSize + messages.size)) {
+            val message = if (i < histSize) historicMessages[i] else messages[i - histSize]
 
             val sender = message.senderPerson
             val senderKey = sender?.getKeyOrName()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index 91b12cc..df43ff1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -41,8 +41,8 @@
 import com.android.internal.util.ContrastColorUtil;
 import com.android.internal.widget.NotificationActionListLayout;
 import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
 import com.android.systemui.UiOffloadThread;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.ViewTransformationHelper;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
index 0c248f5..0c0cb07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AnimationFilter.java
@@ -31,7 +31,6 @@
     boolean animateAlpha;
     boolean animateX;
     public boolean animateY;
-    ArraySet<View> animateYViews = new ArraySet<>();
     boolean animateZ;
     boolean animateHeight;
     boolean animateTopInset;
@@ -87,13 +86,8 @@
         return this;
     }
 
-    public AnimationFilter animateY(View view) {
-        animateYViews.add(view);
-        return this;
-    }
-
     public boolean shouldAnimateY(View view) {
-        return animateY || animateYViews.contains(view);
+        return animateY;
     }
 
     /**
@@ -118,7 +112,6 @@
         animateAlpha |= filter.animateAlpha;
         animateX |= filter.animateX;
         animateY |= filter.animateY;
-        animateYViews.addAll(filter.animateYViews);
         animateZ |= filter.animateZ;
         animateHeight |= filter.animateHeight;
         animateTopInset |= filter.animateTopInset;
@@ -131,7 +124,6 @@
         animateAlpha = false;
         animateX = false;
         animateY = false;
-        animateYViews.clear();
         animateZ = false;
         animateHeight = false;
         animateTopInset = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index de0f247..57504b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -2399,12 +2399,13 @@
     private void updateContentHeight() {
         final float scrimTopPadding = mAmbientState.isOnKeyguard() ? 0 : mMinimumPaddings;
         final int shelfIntrinsicHeight = mShelf != null ? mShelf.getIntrinsicHeight() : 0;
+        final int footerIntrinsicHeight = mFooterView != null ? mFooterView.getIntrinsicHeight() : 0;
         final float height =
                 (int) scrimTopPadding + (int) mNotificationStackSizeCalculator.computeHeight(
                         /* notificationStackScrollLayout= */ this, mMaxDisplayedNotifications,
                         shelfIntrinsicHeight);
         mIntrinsicContentHeight = height;
-        mScrollViewFields.sendStackHeight(height);
+        mScrollViewFields.sendStackHeight(height + footerIntrinsicHeight);
 
         // The topPadding can be bigger than the regular padding when qs is expanded, in that
         // state the maxPanelHeight and the contentHeight should be bigger
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index ab62ed6..5963d35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -29,7 +29,6 @@
 
 import com.android.app.animation.Interpolators;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.keyguard.KeyguardSliceView;
 import com.android.systemui.res.R;
 import com.android.systemui.shared.clocks.AnimatableClockView;
 import com.android.systemui.statusbar.NotificationShelf;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index f097d06..ef14557 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -657,7 +657,7 @@
         }
         ObjectAnimator previousAnimator = getChildTag(child, TAG_ANIMATOR_TRANSLATION_Y);
         AnimationFilter filter = properties.getAnimationFilter();
-        if (!filter.shouldAnimateY(child)) {
+        if (!filter.animateY) {
             // just a local update was performed
             if (previousAnimator != null) {
                 // we need to increase all animation keyframes of the previous animator by the
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
index eb81c46..1358cfd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
@@ -30,7 +30,6 @@
 
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.AutoHideUiElement;
 
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
index d513f8d..398c1d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
@@ -14,8 +14,8 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.plugins.DarkIconDispatcher.getTint;
 import static com.android.settingslib.flags.Flags.newStatusBarIcons;
+import static com.android.systemui.plugins.DarkIconDispatcher.getTint;
 
 import android.animation.ArgbEvaluator;
 import android.content.Context;
@@ -28,16 +28,16 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
 
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-import javax.inject.Inject;
-
 import kotlinx.coroutines.flow.FlowKt;
 import kotlinx.coroutines.flow.MutableStateFlow;
 import kotlinx.coroutines.flow.StateFlow;
 import kotlinx.coroutines.flow.StateFlowKt;
 
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+import javax.inject.Inject;
+
 /**
  */
 @SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index 033659b..3063aed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -57,12 +57,12 @@
 
 import dagger.Lazy;
 
+import kotlinx.coroutines.ExperimentalCoroutinesApi;
+
 import java.util.ArrayList;
 
 import javax.inject.Inject;
 
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
-
 /**
  * Implementation of DozeHost for SystemUI.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 8ec8d1c..68457ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -58,6 +58,11 @@
 import com.android.systemui.util.settings.GlobalSettings;
 import com.android.systemui.util.time.SystemClock;
 
+import kotlinx.coroutines.flow.Flow;
+import kotlinx.coroutines.flow.MutableStateFlow;
+import kotlinx.coroutines.flow.StateFlow;
+import kotlinx.coroutines.flow.StateFlowKt;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -68,11 +73,6 @@
 
 import javax.inject.Inject;
 
-import kotlinx.coroutines.flow.Flow;
-import kotlinx.coroutines.flow.MutableStateFlow;
-import kotlinx.coroutines.flow.StateFlow;
-import kotlinx.coroutines.flow.StateFlowKt;
-
 /** A implementation of HeadsUpManager for phone. */
 @SysUISingleton
 public class HeadsUpManagerPhone extends BaseHeadsUpManager implements
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java
index f043fcf..abfe6a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissHandler.java
@@ -18,7 +18,6 @@
 
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 
-
 /** Executes actions that require the screen to be unlocked. */
 public interface KeyguardDismissHandler {
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
index c6690c9..c4e0f31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -32,8 +32,8 @@
 
 import com.android.app.animation.Interpolators;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.res.R;
 import com.android.systemui.keyguard.KeyguardIndication;
+import com.android.systemui.res.R;
 
 /**
  * A view to show hints on Keyguard ("Swipe up to unlock", "Tap again to open").
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 302bdcc..3cdf68f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -48,18 +48,19 @@
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
 import com.android.systemui.res.R;
 import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher.DarkChange;
+import com.android.systemui.statusbar.phone.ui.TintedIconManager;
 import com.android.systemui.statusbar.phone.userswitcher.StatusBarUserSwitcherContainer;
 import com.android.systemui.user.ui.binder.StatusBarUserChipViewBinder;
 import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel;
 
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
 import kotlinx.coroutines.flow.FlowKt;
 import kotlinx.coroutines.flow.MutableStateFlow;
 import kotlinx.coroutines.flow.StateFlow;
 import kotlinx.coroutines.flow.StateFlowKt;
 
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
 /**
  * The header group on Keyguard.
  */
@@ -421,7 +422,7 @@
     }
 
     /** Should only be called from {@link KeyguardStatusBarViewController}. */
-    void onThemeChanged(StatusBarIconController.TintedIconManager iconManager) {
+    void onThemeChanged(TintedIconManager iconManager) {
         mBatteryView.setColorsFromContext(mContext);
         updateIconsAndTextColors(iconManager);
     }
@@ -438,7 +439,7 @@
         }
     }
 
-    private void updateIconsAndTextColors(StatusBarIconController.TintedIconManager iconManager) {
+    private void updateIconsAndTextColors(TintedIconManager iconManager) {
         @ColorInt int textColor = Utils.getColorAttrDefaultColor(mContext,
                 R.attr.wallpaperTextColor);
         float luminance = Color.luminance(textColor);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index 3343779..45d86c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -19,8 +19,8 @@
 import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
 import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO;
 
-import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
 import static com.android.systemui.Flags.updateUserSwitcherBackground;
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
 
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -46,11 +46,10 @@
 import com.android.systemui.battery.BatteryMeterViewController;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.log.core.LogLevel;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
 import com.android.systemui.shade.ShadeViewStateProvider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationMediaManager;
@@ -65,6 +64,8 @@
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.fragment.StatusBarIconBlocklistKt;
 import com.android.systemui.statusbar.phone.fragment.StatusBarSystemEventDefaultAnimator;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
+import com.android.systemui.statusbar.phone.ui.TintedIconManager;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -108,7 +109,7 @@
     private final BatteryController mBatteryController;
     private final UserInfoController mUserInfoController;
     private final StatusBarIconController mStatusBarIconController;
-    private final StatusBarIconController.TintedIconManager.Factory mTintedIconManagerFactory;
+    private final TintedIconManager.Factory mTintedIconManagerFactory;
     private final BatteryMeterViewController mBatteryMeterViewController;
     private final ShadeViewStateProvider mShadeViewStateProvider;
     private final KeyguardStateController mKeyguardStateController;
@@ -118,7 +119,6 @@
     private final BiometricUnlockController mBiometricUnlockController;
     private final SysuiStatusBarStateController mStatusBarStateController;
     private final StatusBarContentInsetsProvider mInsetsProvider;
-    private final FeatureFlags mFeatureFlags;
     private final UserManager mUserManager;
     private final StatusBarUserChipViewModel mStatusBarUserChipViewModel;
     private final SecureSettings mSecureSettings;
@@ -250,7 +250,7 @@
     private final int mNotificationsHeaderCollideDistance;
 
     private boolean mBatteryListening;
-    private StatusBarIconController.TintedIconManager mTintedIconManager;
+    private TintedIconManager mTintedIconManager;
 
     private float mKeyguardStatusBarAnimateAlpha = 1f;
     /**
@@ -283,7 +283,7 @@
             BatteryController batteryController,
             UserInfoController userInfoController,
             StatusBarIconController statusBarIconController,
-            StatusBarIconController.TintedIconManager.Factory tintedIconManagerFactory,
+            TintedIconManager.Factory tintedIconManagerFactory,
             BatteryMeterViewController batteryMeterViewController,
             ShadeViewStateProvider shadeViewStateProvider,
             KeyguardStateController keyguardStateController,
@@ -293,7 +293,6 @@
             BiometricUnlockController biometricUnlockController,
             SysuiStatusBarStateController statusBarStateController,
             StatusBarContentInsetsProvider statusBarContentInsetsProvider,
-            FeatureFlags featureFlags,
             UserManager userManager,
             StatusBarUserChipViewModel userChipViewModel,
             SecureSettings secureSettings,
@@ -321,7 +320,6 @@
         mBiometricUnlockController = biometricUnlockController;
         mStatusBarStateController = statusBarStateController;
         mInsetsProvider = statusBarContentInsetsProvider;
-        mFeatureFlags = featureFlags;
         mUserManager = userManager;
         mStatusBarUserChipViewModel = userChipViewModel;
         mSecureSettings = secureSettings;
@@ -707,7 +705,7 @@
     }
 
     private boolean isMigrationEnabled() {
-        return mFeatureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW);
+        return SceneContainerFlag.isEnabled();
     }
 
     private final ContentObserver mVolumeSettingObserver = new ContentObserver(null) {
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 d975009..3c68805 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -44,7 +44,6 @@
 
 import androidx.lifecycle.Observer;
 
-import com.android.systemui.res.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.DisplayId;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -56,9 +55,11 @@
 import com.android.systemui.privacy.logging.PrivacyLogger;
 import com.android.systemui.qs.tiles.DndTile;
 import com.android.systemui.qs.tiles.RotationLockTile;
+import com.android.systemui.res.R;
 import com.android.systemui.screenrecord.RecordingController;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.CastController.CastDevice;
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 02293a2..0a88d63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -83,6 +83,8 @@
 import com.android.systemui.util.wakelock.WakeLock;
 import com.android.systemui.wallpapers.data.repository.WallpaperRepository;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -91,8 +93,6 @@
 
 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).
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
deleted file mode 100644
index d7cbe5d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ /dev/null
@@ -1,602 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_BINDABLE;
-import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
-import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE_NEW;
-import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI_NEW;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.os.Bundle;
-import android.text.TextUtils;
-import android.util.ArraySet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-import android.widget.LinearLayout.LayoutParams;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.internal.statusbar.StatusBarIcon;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.demomode.DemoModeCommandReceiver;
-import com.android.systemui.plugins.DarkIconDispatcher;
-import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
-import com.android.systemui.res.R;
-import com.android.systemui.statusbar.BaseStatusBarFrameLayout;
-import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.statusbar.StatusIconDisplayable;
-import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
-import com.android.systemui.statusbar.phone.StatusBarIconHolder.BindableIconHolder;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
-import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
-import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconsBinder;
-import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
-import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
-import com.android.systemui.statusbar.pipeline.shared.ui.view.ModernStatusBarView;
-import com.android.systemui.statusbar.pipeline.wifi.ui.WifiUiAdapter;
-import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
-import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel;
-import com.android.systemui.util.Assert;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-public interface StatusBarIconController {
-
-    /**
-     * When an icon is added with TAG_PRIMARY, it will be treated as the primary icon
-     * in that slot and not added as a sub slot.
-     */
-    int TAG_PRIMARY = 0;
-
-    /** */
-    void addIconGroup(IconManager iconManager);
-    /** */
-    void removeIconGroup(IconManager iconManager);
-
-    /** Refresh the state of an IconManager by recreating the views */
-    void refreshIconGroup(IconManager iconManager);
-
-    /**
-     * Adds or updates an icon that comes from an active tile service.
-     *
-     * If the icon is null, the icon will be removed.
-     */
-    void setIconFromTile(String slot, @Nullable StatusBarIcon icon);
-
-    /** Removes an icon that had come from an active tile service. */
-    void removeIconForTile(String slot);
-
-    /** Adds or updates an icon for the given slot for **internal system icons**. */
-    void setIcon(String slot, int resourceId, CharSequence contentDescription);
-
-    /**
-     * Sets up a wifi icon using the new data pipeline. No effect if the wifi icon has already been
-     * set up (inflated and added to the view hierarchy).
-     */
-    void setNewWifiIcon();
-
-    /**
-     * Notify this class that there is a new set of mobile icons to display, keyed off of this list
-     * of subIds. The icons will be added and bound to the mobile data pipeline via
-     * {@link com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconBinder}.
-     */
-    void setNewMobileIconSubIds(List<Integer> subIds);
-    /**
-     * Display the no calling & SMS icons.
-     */
-    void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states);
-
-    /**
-     * Display the no calling & SMS icons.
-     */
-    void setNoCallingIcons(String slot, List<CallIndicatorIconState> states);
-
-    public void setIconVisibility(String slot, boolean b);
-
-    /**
-     * Sets the live region mode for the icon
-     *
-     * @param slot                    Icon slot to set region for
-     * @param accessibilityLiveRegion live region mode for the icon
-     * @see android.view.View#setAccessibilityLiveRegion(int)
-     */
-    void setIconAccessibilityLiveRegion(String slot, int accessibilityLiveRegion);
-
-    /**
-     * If you don't know what to pass for `tag`, either remove all icons for slot, or use
-     * TAG_PRIMARY to refer to the first icon at a given slot.
-     */
-    void removeIcon(String slot, int tag);
-
-    // TODO: See if we can rename this tunable name.
-    String ICON_HIDE_LIST = "icon_blacklist";
-
-    /** Reads the default hide list from config value unless hideListStr is provided. */
-    static ArraySet<String> getIconHideList(Context context, String hideListStr) {
-        ArraySet<String> ret = new ArraySet<>();
-        String[] hideList = hideListStr == null
-                ? context.getResources().getStringArray(R.array.config_statusBarIconsToExclude)
-                : hideListStr.split(",");
-        for (String slot : hideList) {
-            if (!TextUtils.isEmpty(slot)) {
-                ret.add(slot);
-            }
-        }
-        return ret;
-    }
-
-    /**
-     * Version of ViewGroup that observes state from the DarkIconDispatcher.
-     */
-    class DarkIconManager extends IconManager {
-        private final DarkIconDispatcher mDarkIconDispatcher;
-        private final int mIconHorizontalMargin;
-
-        public DarkIconManager(
-                LinearLayout linearLayout,
-                StatusBarLocation location,
-                WifiUiAdapter wifiUiAdapter,
-                MobileUiAdapter mobileUiAdapter,
-                MobileContextProvider mobileContextProvider,
-                DarkIconDispatcher darkIconDispatcher) {
-            super(linearLayout,
-                    location,
-                    wifiUiAdapter,
-                    mobileUiAdapter,
-                    mobileContextProvider);
-            mIconHorizontalMargin = mContext.getResources().getDimensionPixelSize(
-                    R.dimen.status_bar_icon_horizontal_margin);
-            mDarkIconDispatcher = darkIconDispatcher;
-        }
-
-        @Override
-        protected void onIconAdded(int index, String slot, boolean blocked,
-                StatusBarIconHolder holder) {
-            StatusIconDisplayable view = addHolder(index, slot, blocked, holder);
-            mDarkIconDispatcher.addDarkReceiver((DarkReceiver) view);
-        }
-
-        @Override
-        protected LayoutParams onCreateLayoutParams() {
-            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
-                    ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
-            lp.setMargins(mIconHorizontalMargin, 0, mIconHorizontalMargin, 0);
-            return lp;
-        }
-
-        @Override
-        protected void destroy() {
-            for (int i = 0; i < mGroup.getChildCount(); i++) {
-                mDarkIconDispatcher.removeDarkReceiver((DarkReceiver) mGroup.getChildAt(i));
-            }
-            mGroup.removeAllViews();
-        }
-
-        @Override
-        protected void onRemoveIcon(int viewIndex) {
-            mDarkIconDispatcher.removeDarkReceiver((DarkReceiver) mGroup.getChildAt(viewIndex));
-            super.onRemoveIcon(viewIndex);
-        }
-
-        @Override
-        public void onSetIcon(int viewIndex, StatusBarIcon icon) {
-            super.onSetIcon(viewIndex, icon);
-            mDarkIconDispatcher.applyDark((DarkReceiver) mGroup.getChildAt(viewIndex));
-        }
-
-        @Override
-        protected DemoStatusIcons createDemoStatusIcons() {
-            DemoStatusIcons icons = super.createDemoStatusIcons();
-            mDarkIconDispatcher.addDarkReceiver(icons);
-
-            return icons;
-        }
-
-        @Override
-        protected void exitDemoMode() {
-            mDarkIconDispatcher.removeDarkReceiver(mDemoStatusIcons);
-            super.exitDemoMode();
-        }
-
-        @SysUISingleton
-        public static class Factory {
-            private final WifiUiAdapter mWifiUiAdapter;
-            private final MobileContextProvider mMobileContextProvider;
-            private final MobileUiAdapter mMobileUiAdapter;
-            private final DarkIconDispatcher mDarkIconDispatcher;
-
-            @Inject
-            public Factory(
-                    WifiUiAdapter wifiUiAdapter,
-                    MobileContextProvider mobileContextProvider,
-                    MobileUiAdapter mobileUiAdapter,
-                    DarkIconDispatcher darkIconDispatcher) {
-                mWifiUiAdapter = wifiUiAdapter;
-                mMobileContextProvider = mobileContextProvider;
-                mMobileUiAdapter = mobileUiAdapter;
-                mDarkIconDispatcher = darkIconDispatcher;
-            }
-
-            public DarkIconManager create(LinearLayout group, StatusBarLocation location) {
-                return new DarkIconManager(
-                        group,
-                        location,
-                        mWifiUiAdapter,
-                        mMobileUiAdapter,
-                        mMobileContextProvider,
-                        mDarkIconDispatcher);
-            }
-        }
-    }
-
-    /**
-     *
-     */
-    class TintedIconManager extends IconManager {
-        // The main tint, used as the foreground in non layer drawables
-        private int mColor;
-        // To be used as the main tint in drawables that wish to have a layer
-        private int mForegroundColor;
-
-        public TintedIconManager(
-                ViewGroup group,
-                StatusBarLocation location,
-                WifiUiAdapter wifiUiAdapter,
-                MobileUiAdapter mobileUiAdapter,
-                MobileContextProvider mobileContextProvider
-        ) {
-            super(group,
-                    location,
-                    wifiUiAdapter,
-                    mobileUiAdapter,
-                    mobileContextProvider);
-        }
-
-        @Override
-        protected void onIconAdded(int index, String slot, boolean blocked,
-                StatusBarIconHolder holder) {
-            StatusIconDisplayable view = addHolder(index, slot, blocked, holder);
-            view.setStaticDrawableColor(mColor, mForegroundColor);
-            view.setDecorColor(mColor);
-        }
-
-        /**
-         * Most icons are a single layer, and tintColor will be used as the tint in those cases.
-         * For icons that have a background, foregroundColor becomes the contrasting tint used
-         * for the foreground.
-         *
-         * @param tintColor the main tint to use for the icons in the group
-         * @param foregroundColor used as the main tint for layer-ish drawables where tintColor is
-         *                        being used as the background
-         */
-        public void setTint(int tintColor, int foregroundColor) {
-            mColor = tintColor;
-            mForegroundColor = foregroundColor;
-
-            for (int i = 0; i < mGroup.getChildCount(); i++) {
-                View child = mGroup.getChildAt(i);
-                if (child instanceof StatusIconDisplayable) {
-                    StatusIconDisplayable icon = (StatusIconDisplayable) child;
-                    icon.setStaticDrawableColor(mColor, mForegroundColor);
-                    icon.setDecorColor(mColor);
-                }
-            }
-
-            if (mDemoStatusIcons != null) {
-                mDemoStatusIcons.setColor(tintColor, foregroundColor);
-            }
-        }
-
-        @Override
-        protected DemoStatusIcons createDemoStatusIcons() {
-            DemoStatusIcons icons = super.createDemoStatusIcons();
-            icons.setColor(mColor, mForegroundColor);
-            return icons;
-        }
-
-        @SysUISingleton
-        public static class Factory {
-            private final WifiUiAdapter mWifiUiAdapter;
-            private final MobileContextProvider mMobileContextProvider;
-            private final MobileUiAdapter mMobileUiAdapter;
-
-            @Inject
-            public Factory(
-                    WifiUiAdapter wifiUiAdapter,
-                    MobileUiAdapter mobileUiAdapter,
-                    MobileContextProvider mobileContextProvider
-            ) {
-                mWifiUiAdapter = wifiUiAdapter;
-                mMobileUiAdapter = mobileUiAdapter;
-                mMobileContextProvider = mobileContextProvider;
-            }
-
-            public TintedIconManager create(ViewGroup group, StatusBarLocation location) {
-                return new TintedIconManager(
-                        group,
-                        location,
-                        mWifiUiAdapter,
-                        mMobileUiAdapter,
-                        mMobileContextProvider);
-            }
-        }
-    }
-
-    /**
-     * Turns info from StatusBarIconController into ImageViews in a ViewGroup.
-     */
-    class IconManager implements DemoModeCommandReceiver {
-        protected final ViewGroup mGroup;
-        private final MobileContextProvider mMobileContextProvider;
-        private final LocationBasedWifiViewModel mWifiViewModel;
-        private final MobileIconsViewModel mMobileIconsViewModel;
-
-        protected final Context mContext;
-        protected int mIconSize;
-        // Whether or not these icons show up in dumpsys
-        protected boolean mShouldLog = false;
-        private StatusBarIconController mController;
-        private final StatusBarLocation mLocation;
-
-        // Enables SystemUI demo mode to take effect in this group
-        protected boolean mDemoable = true;
-        private boolean mIsInDemoMode;
-        protected DemoStatusIcons mDemoStatusIcons;
-
-        protected ArrayList<String> mBlockList = new ArrayList<>();
-
-        public IconManager(
-                ViewGroup group,
-                StatusBarLocation location,
-                WifiUiAdapter wifiUiAdapter,
-                MobileUiAdapter mobileUiAdapter,
-                MobileContextProvider mobileContextProvider
-        ) {
-            mGroup = group;
-            mMobileContextProvider = mobileContextProvider;
-            mContext = group.getContext();
-            mLocation = location;
-
-            reloadDimens();
-
-            // This starts the flow for the new pipeline, and will notify us of changes via
-            // {@link #setNewMobileIconIds}
-            mMobileIconsViewModel = mobileUiAdapter.getMobileIconsViewModel();
-            MobileIconsBinder.bind(mGroup, mMobileIconsViewModel);
-
-            mWifiViewModel = wifiUiAdapter.bindGroup(mGroup, mLocation);
-        }
-
-        public boolean isDemoable() {
-            return mDemoable;
-        }
-
-        public void setIsDemoable(boolean demoable) {
-            mDemoable = demoable;
-        }
-
-        void setController(StatusBarIconController controller) {
-            mController = controller;
-        }
-
-        public void setBlockList(@Nullable List<String> blockList) {
-            Assert.isMainThread();
-            mBlockList.clear();
-            mBlockList.addAll(blockList);
-            if (mController != null) {
-                mController.refreshIconGroup(this);
-            }
-        }
-
-        public void setShouldLog(boolean should) {
-            mShouldLog = should;
-        }
-
-        public boolean shouldLog() {
-            return mShouldLog;
-        }
-
-        protected void onIconAdded(int index, String slot, boolean blocked,
-                StatusBarIconHolder holder) {
-            addHolder(index, slot, blocked, holder);
-        }
-
-        protected StatusIconDisplayable addHolder(int index, String slot, boolean blocked,
-                StatusBarIconHolder holder) {
-            // This is a little hacky, and probably regrettable, but just set `blocked` on any icon
-            // that is in our blocked list, then we'll never see it
-            if (mBlockList.contains(slot)) {
-                blocked = true;
-            }
-            switch (holder.getType()) {
-                case TYPE_ICON:
-                    return addIcon(index, slot, blocked, holder.getIcon());
-
-                case TYPE_WIFI_NEW:
-                    return addNewWifiIcon(index, slot);
-
-                case TYPE_MOBILE_NEW:
-                    return addNewMobileIcon(index, slot, holder.getTag());
-
-                case TYPE_BINDABLE:
-                    // Safe cast, since only BindableIconHolders can set this tag on themselves
-                    return addBindableIcon((BindableIconHolder) holder, index);
-            }
-
-            return null;
-        }
-
-        @VisibleForTesting
-        protected StatusBarIconView addIcon(int index, String slot, boolean blocked,
-                StatusBarIcon icon) {
-            StatusBarIconView view = onCreateStatusBarIconView(slot, blocked);
-            view.set(icon);
-            mGroup.addView(view, index, onCreateLayoutParams());
-            return view;
-        }
-
-        /**
-         * ModernStatusBarViews can be created and bound, and thus do not need to update their
-         *  drawable by sending multiple calls to setIcon. Instead, by using a bindable
-         * icon view, we can simply create the icon when requested and allow the
-         * ViewBinder to control its visual state.
-         */
-        protected StatusIconDisplayable addBindableIcon(BindableIconHolder holder, int index) {
-            ModernStatusBarView view = holder.getInitializer().createAndBind(mContext);
-            mGroup.addView(view, index, onCreateLayoutParams());
-            return view;
-        }
-
-        protected StatusIconDisplayable addNewWifiIcon(int index, String slot) {
-            ModernStatusBarWifiView view = onCreateModernStatusBarWifiView(slot);
-            mGroup.addView(view, index, onCreateLayoutParams());
-
-            if (mIsInDemoMode) {
-                mDemoStatusIcons.addModernWifiView(mWifiViewModel);
-            }
-
-            return view;
-        }
-
-
-        protected StatusIconDisplayable addNewMobileIcon(
-                int index,
-                String slot,
-                int subId
-        ) {
-            BaseStatusBarFrameLayout view = onCreateModernStatusBarMobileView(slot, subId);
-            mGroup.addView(view, index, onCreateLayoutParams());
-
-            if (mIsInDemoMode) {
-                Context mobileContext = mMobileContextProvider
-                        .getMobileContextForSub(subId, mContext);
-                mDemoStatusIcons.addModernMobileView(
-                        mobileContext,
-                        mMobileIconsViewModel.getLogger(),
-                        subId);
-            }
-
-            return view;
-        }
-
-        private StatusBarIconView onCreateStatusBarIconView(String slot, boolean blocked) {
-            return new StatusBarIconView(mContext, slot, null, blocked);
-        }
-
-        private ModernStatusBarWifiView onCreateModernStatusBarWifiView(String slot) {
-            return ModernStatusBarWifiView.constructAndBind(mContext, slot, mWifiViewModel);
-        }
-
-        private ModernStatusBarMobileView onCreateModernStatusBarMobileView(
-                String slot, int subId) {
-            Context mobileContext = mMobileContextProvider.getMobileContextForSub(subId, mContext);
-            return ModernStatusBarMobileView
-                    .constructAndBind(
-                            mobileContext,
-                            mMobileIconsViewModel.getLogger(),
-                            slot,
-                            mMobileIconsViewModel.viewModelForSub(subId, mLocation)
-                        );
-        }
-
-        protected LinearLayout.LayoutParams onCreateLayoutParams() {
-            return new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
-        }
-
-        protected void destroy() {
-            mGroup.removeAllViews();
-        }
-
-        protected void reloadDimens() {
-            mIconSize = mContext.getResources().getDimensionPixelSize(
-                    com.android.internal.R.dimen.status_bar_icon_size_sp);
-        }
-
-        protected void onRemoveIcon(int viewIndex) {
-            if (mIsInDemoMode) {
-                mDemoStatusIcons.onRemoveIcon((StatusIconDisplayable) mGroup.getChildAt(viewIndex));
-            }
-            mGroup.removeViewAt(viewIndex);
-        }
-
-        public void onSetIcon(int viewIndex, StatusBarIcon icon) {
-            StatusBarIconView view = (StatusBarIconView) mGroup.getChildAt(viewIndex);
-            view.set(icon);
-        }
-
-        public void onSetIconHolder(int viewIndex, StatusBarIconHolder holder) {
-            switch (holder.getType()) {
-                case TYPE_ICON:
-                    onSetIcon(viewIndex, holder.getIcon());
-                    return;
-                case TYPE_MOBILE_NEW:
-                case TYPE_WIFI_NEW:
-                case TYPE_BINDABLE:
-                    // Nothing, the new icons update themselves
-                    return;
-                default:
-                    break;
-            }
-        }
-
-        @Override
-        public void dispatchDemoCommand(String command, Bundle args) {
-            if (!mDemoable) {
-                return;
-            }
-
-            mDemoStatusIcons.dispatchDemoCommand(command, args);
-        }
-
-        @Override
-        public void onDemoModeStarted() {
-            mIsInDemoMode = true;
-            if (mDemoStatusIcons == null) {
-                mDemoStatusIcons = createDemoStatusIcons();
-                mDemoStatusIcons.addModernWifiView(mWifiViewModel);
-            }
-            mDemoStatusIcons.onDemoModeStarted();
-        }
-
-        @Override
-        public void onDemoModeFinished() {
-            if (mDemoStatusIcons != null) {
-                mDemoStatusIcons.onDemoModeFinished();
-                exitDemoMode();
-                mIsInDemoMode = false;
-            }
-        }
-
-        protected void exitDemoMode() {
-            mDemoStatusIcons.remove();
-            mDemoStatusIcons = null;
-        }
-
-        protected DemoStatusIcons createDemoStatusIcons() {
-            return new DemoStatusIcons(
-                    (LinearLayout) mGroup,
-                    mMobileIconsViewModel,
-                    mLocation,
-                    mIconSize
-            );
-        }
-    }
-}
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 a141b53..f35d199 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -108,6 +108,10 @@
 
 import kotlin.Unit;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+import kotlinx.coroutines.ExperimentalCoroutinesApi;
+import kotlinx.coroutines.Job;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -117,10 +121,6 @@
 
 import javax.inject.Inject;
 
-import kotlinx.coroutines.CoroutineDispatcher;
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
-import kotlinx.coroutines.Job;
-
 /**
  * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
  * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
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 5d27467..e1a7f22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -90,7 +90,6 @@
 
 import javax.inject.Inject;
 
-
 /**
  * Status bar implementation of {@link NotificationActivityStarter}.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 703b3c6..ba59398 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -23,11 +23,12 @@
 import android.util.Log;
 
 import com.android.settingslib.mobile.TelephonyIcons;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.connectivity.IconState;
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.connectivity.SignalCallback;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.policy.SecurityController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index 7910e6f..144939d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -38,6 +38,7 @@
 import com.android.systemui.statusbar.notification.stack.AnimationFilter;
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
 import com.android.systemui.statusbar.notification.stack.ViewState;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java
index 93db916..82f9eba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SysuiDarkIconDispatcher.java
@@ -21,11 +21,11 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.plugins.DarkIconDispatcher;
 
+import kotlinx.coroutines.flow.StateFlow;
+
 import java.util.ArrayList;
 import java.util.Collection;
 
-import kotlinx.coroutines.flow.StateFlow;
-
 /**
  * Dispatches events to {@link DarkReceiver}s about changes in darkness, tint area
  * and dark intensity.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index c52132f..4fc11df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -60,14 +60,14 @@
 import com.android.systemui.statusbar.phone.NotificationIconContainer;
 import com.android.systemui.statusbar.phone.PhoneStatusBarView;
 import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
 import com.android.systemui.statusbar.phone.StatusBarLocation;
 import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
 import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
 import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent.Startable;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener;
+import com.android.systemui.statusbar.phone.ui.DarkIconManager;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder;
 import com.android.systemui.statusbar.pipeline.shared.ui.binder.StatusBarVisibilityChangeListener;
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel;
@@ -79,8 +79,6 @@
 import com.android.systemui.util.CarrierConfigTracker.DefaultDataSubscriptionChangedListener;
 import com.android.systemui.util.settings.SecureSettings;
 
-import kotlin.Unit;
-
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -91,6 +89,8 @@
 
 import javax.inject.Inject;
 
+import kotlin.Unit;
+
 import kotlinx.coroutines.DisposableHandle;
 
 /**
@@ -143,7 +143,7 @@
     private final CollapsedStatusBarViewModel mCollapsedStatusBarViewModel;
     private final CollapsedStatusBarViewBinder mCollapsedStatusBarViewBinder;
     private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
-    private final StatusBarIconController.DarkIconManager.Factory mDarkIconManagerFactory;
+    private final DarkIconManager.Factory mDarkIconManagerFactory;
     private final SecureSettings mSecureSettings;
     private final Executor mMainExecutor;
     private final DumpManager mDumpManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/DarkIconManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/DarkIconManager.java
new file mode 100644
index 0000000..8871dae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/DarkIconManager.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.ui;
+
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.statusbar.StatusIconDisplayable;
+import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
+import com.android.systemui.statusbar.phone.DemoStatusIcons;
+import com.android.systemui.statusbar.phone.StatusBarIconHolder;
+import com.android.systemui.statusbar.phone.StatusBarLocation;
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
+import com.android.systemui.statusbar.pipeline.wifi.ui.WifiUiAdapter;
+
+import javax.inject.Inject;
+
+/**
+ * Version of {@link IconManager} that observes state from the DarkIconDispatcher.
+ */
+public class DarkIconManager extends IconManager {
+    private final DarkIconDispatcher mDarkIconDispatcher;
+    private final int mIconHorizontalMargin;
+
+    public DarkIconManager(
+            LinearLayout linearLayout,
+            StatusBarLocation location,
+            WifiUiAdapter wifiUiAdapter,
+            MobileUiAdapter mobileUiAdapter,
+            MobileContextProvider mobileContextProvider,
+            DarkIconDispatcher darkIconDispatcher) {
+        super(linearLayout,
+                location,
+                wifiUiAdapter,
+                mobileUiAdapter,
+                mobileContextProvider);
+        mIconHorizontalMargin = mContext.getResources().getDimensionPixelSize(
+                com.android.systemui.res.R.dimen.status_bar_icon_horizontal_margin);
+        mDarkIconDispatcher = darkIconDispatcher;
+    }
+
+    @Override
+    protected void onIconAdded(int index, String slot, boolean blocked,
+            StatusBarIconHolder holder) {
+        StatusIconDisplayable view = addHolder(index, slot, blocked, holder);
+        mDarkIconDispatcher.addDarkReceiver(view);
+    }
+
+    @Override
+    protected LinearLayout.LayoutParams onCreateLayoutParams() {
+        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
+        lp.setMargins(mIconHorizontalMargin, 0, mIconHorizontalMargin, 0);
+        return lp;
+    }
+
+    @Override
+    protected void destroy() {
+        for (int i = 0; i < mGroup.getChildCount(); i++) {
+            mDarkIconDispatcher.removeDarkReceiver(
+                    (DarkIconDispatcher.DarkReceiver) mGroup.getChildAt(i));
+        }
+        mGroup.removeAllViews();
+    }
+
+    @Override
+    protected void onRemoveIcon(int viewIndex) {
+        mDarkIconDispatcher.removeDarkReceiver(
+                (DarkIconDispatcher.DarkReceiver) mGroup.getChildAt(viewIndex));
+        super.onRemoveIcon(viewIndex);
+    }
+
+    @Override
+    public void onSetIcon(int viewIndex, StatusBarIcon icon) {
+        super.onSetIcon(viewIndex, icon);
+        mDarkIconDispatcher.applyDark(
+                (DarkIconDispatcher.DarkReceiver) mGroup.getChildAt(viewIndex));
+    }
+
+    @Override
+    protected DemoStatusIcons createDemoStatusIcons() {
+        DemoStatusIcons icons = super.createDemoStatusIcons();
+        mDarkIconDispatcher.addDarkReceiver(icons);
+
+        return icons;
+    }
+
+    @Override
+    protected void exitDemoMode() {
+        mDarkIconDispatcher.removeDarkReceiver(mDemoStatusIcons);
+        super.exitDemoMode();
+    }
+
+    @SysUISingleton
+    public static class Factory {
+        private final WifiUiAdapter mWifiUiAdapter;
+        private final MobileContextProvider mMobileContextProvider;
+        private final MobileUiAdapter mMobileUiAdapter;
+        private final DarkIconDispatcher mDarkIconDispatcher;
+
+        @Inject
+        public Factory(
+                WifiUiAdapter wifiUiAdapter,
+                MobileContextProvider mobileContextProvider,
+                MobileUiAdapter mobileUiAdapter,
+                DarkIconDispatcher darkIconDispatcher) {
+            mWifiUiAdapter = wifiUiAdapter;
+            mMobileContextProvider = mobileContextProvider;
+            mMobileUiAdapter = mobileUiAdapter;
+            mDarkIconDispatcher = darkIconDispatcher;
+        }
+
+        /** Creates a new {@link DarkIconManager} for the given view group and location. */
+        public DarkIconManager create(LinearLayout group, StatusBarLocation location) {
+            return new DarkIconManager(
+                    group,
+                    location,
+                    mWifiUiAdapter,
+                    mMobileUiAdapter,
+                    mMobileContextProvider,
+                    mDarkIconDispatcher);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java
new file mode 100644
index 0000000..0ed9420
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/IconManager.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.ui;
+
+import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_BINDABLE;
+import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
+import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_MOBILE_NEW;
+import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_WIFI_NEW;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.demomode.DemoModeCommandReceiver;
+import com.android.systemui.statusbar.BaseStatusBarFrameLayout;
+import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.StatusIconDisplayable;
+import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
+import com.android.systemui.statusbar.phone.DemoStatusIcons;
+import com.android.systemui.statusbar.phone.StatusBarIconHolder;
+import com.android.systemui.statusbar.phone.StatusBarLocation;
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
+import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconsBinder;
+import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
+import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
+import com.android.systemui.statusbar.pipeline.shared.ui.view.ModernStatusBarView;
+import com.android.systemui.statusbar.pipeline.wifi.ui.WifiUiAdapter;
+import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
+import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel;
+import com.android.systemui.util.Assert;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Turns info from StatusBarIconController into ImageViews in a ViewGroup.
+ */
+public class IconManager implements DemoModeCommandReceiver {
+    protected final ViewGroup mGroup;
+    private final MobileContextProvider mMobileContextProvider;
+    private final LocationBasedWifiViewModel mWifiViewModel;
+    private final MobileIconsViewModel mMobileIconsViewModel;
+
+    protected final Context mContext;
+    protected int mIconSize;
+    // Whether or not these icons show up in dumpsys
+    protected boolean mShouldLog = false;
+    private StatusBarIconController mController;
+    private final StatusBarLocation mLocation;
+
+    // Enables SystemUI demo mode to take effect in this group
+    protected boolean mDemoable = true;
+    private boolean mIsInDemoMode;
+    protected DemoStatusIcons mDemoStatusIcons;
+
+    protected ArrayList<String> mBlockList = new ArrayList<>();
+
+    public IconManager(
+            ViewGroup group,
+            StatusBarLocation location,
+            WifiUiAdapter wifiUiAdapter,
+            MobileUiAdapter mobileUiAdapter,
+            MobileContextProvider mobileContextProvider
+    ) {
+        mGroup = group;
+        mMobileContextProvider = mobileContextProvider;
+        mContext = group.getContext();
+        mLocation = location;
+
+        reloadDimens();
+
+        // This starts the flow for the new pipeline, and will notify us of changes via
+        // {@link #setNewMobileIconIds}
+        mMobileIconsViewModel = mobileUiAdapter.getMobileIconsViewModel();
+        MobileIconsBinder.bind(mGroup, mMobileIconsViewModel);
+
+        mWifiViewModel = wifiUiAdapter.bindGroup(mGroup, mLocation);
+    }
+
+    public boolean isDemoable() {
+        return mDemoable;
+    }
+
+    void setController(StatusBarIconController controller) {
+        mController = controller;
+    }
+
+    /** Sets the list of slots that should be blocked from showing in the status bar. */
+    public void setBlockList(@Nullable List<String> blockList) {
+        Assert.isMainThread();
+        mBlockList.clear();
+        mBlockList.addAll(blockList);
+        if (mController != null) {
+            mController.refreshIconGroup(this);
+        }
+    }
+
+    /** Sets whether this manager's changes should be dumped in a bug report. */
+    public void setShouldLog(boolean should) {
+        mShouldLog = should;
+    }
+
+    /** Returns true if this manager's changes should be dumped in a bug report. */
+    public boolean shouldLog() {
+        return mShouldLog;
+    }
+
+    protected void onIconAdded(int index, String slot, boolean blocked,
+            StatusBarIconHolder holder) {
+        addHolder(index, slot, blocked, holder);
+    }
+
+    protected StatusIconDisplayable addHolder(int index, String slot, boolean blocked,
+            StatusBarIconHolder holder) {
+        // This is a little hacky, and probably regrettable, but just set `blocked` on any icon
+        // that is in our blocked list, then we'll never see it
+        if (mBlockList.contains(slot)) {
+            blocked = true;
+        }
+        return switch (holder.getType()) {
+            case TYPE_ICON -> addIcon(index, slot, blocked, holder.getIcon());
+            case TYPE_WIFI_NEW -> addNewWifiIcon(index, slot);
+            case TYPE_MOBILE_NEW -> addNewMobileIcon(index, slot, holder.getTag());
+            case TYPE_BINDABLE ->
+                // Safe cast, since only BindableIconHolders can set this tag on themselves
+                addBindableIcon((StatusBarIconHolder.BindableIconHolder) holder, index);
+            default -> null;
+        };
+    }
+
+    @VisibleForTesting
+    protected StatusBarIconView addIcon(int index, String slot, boolean blocked,
+            StatusBarIcon icon) {
+        StatusBarIconView view = onCreateStatusBarIconView(slot, blocked);
+        view.set(icon);
+        mGroup.addView(view, index, onCreateLayoutParams());
+        return view;
+    }
+
+    /**
+     * ModernStatusBarViews can be created and bound, and thus do not need to update their
+     * drawable by sending multiple calls to setIcon. Instead, by using a bindable
+     * icon view, we can simply create the icon when requested and allow the
+     * ViewBinder to control its visual state.
+     */
+    protected StatusIconDisplayable addBindableIcon(StatusBarIconHolder.BindableIconHolder holder,
+            int index) {
+        ModernStatusBarView view = holder.getInitializer().createAndBind(mContext);
+        mGroup.addView(view, index, onCreateLayoutParams());
+        return view;
+    }
+
+    protected StatusIconDisplayable addNewWifiIcon(int index, String slot) {
+        ModernStatusBarWifiView view = onCreateModernStatusBarWifiView(slot);
+        mGroup.addView(view, index, onCreateLayoutParams());
+
+        if (mIsInDemoMode) {
+            mDemoStatusIcons.addModernWifiView(mWifiViewModel);
+        }
+
+        return view;
+    }
+
+
+    protected StatusIconDisplayable addNewMobileIcon(
+            int index,
+            String slot,
+            int subId
+    ) {
+        BaseStatusBarFrameLayout view = onCreateModernStatusBarMobileView(slot, subId);
+        mGroup.addView(view, index, onCreateLayoutParams());
+
+        if (mIsInDemoMode) {
+            Context mobileContext = mMobileContextProvider
+                    .getMobileContextForSub(subId, mContext);
+            mDemoStatusIcons.addModernMobileView(
+                    mobileContext,
+                    mMobileIconsViewModel.getLogger(),
+                    subId);
+        }
+
+        return view;
+    }
+
+    private StatusBarIconView onCreateStatusBarIconView(String slot, boolean blocked) {
+        return new StatusBarIconView(mContext, slot, null, blocked);
+    }
+
+    private ModernStatusBarWifiView onCreateModernStatusBarWifiView(String slot) {
+        return ModernStatusBarWifiView.constructAndBind(mContext, slot, mWifiViewModel);
+    }
+
+    private ModernStatusBarMobileView onCreateModernStatusBarMobileView(
+            String slot, int subId) {
+        Context mobileContext = mMobileContextProvider.getMobileContextForSub(subId, mContext);
+        return ModernStatusBarMobileView
+                .constructAndBind(
+                        mobileContext,
+                        mMobileIconsViewModel.getLogger(),
+                        slot,
+                        mMobileIconsViewModel.viewModelForSub(subId, mLocation)
+                );
+    }
+
+    protected LinearLayout.LayoutParams onCreateLayoutParams() {
+        return new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
+    }
+
+    protected void destroy() {
+        mGroup.removeAllViews();
+    }
+
+    protected void reloadDimens() {
+        mIconSize = mContext.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_icon_size_sp);
+    }
+
+    protected void onRemoveIcon(int viewIndex) {
+        if (mIsInDemoMode) {
+            mDemoStatusIcons.onRemoveIcon((StatusIconDisplayable) mGroup.getChildAt(viewIndex));
+        }
+        mGroup.removeViewAt(viewIndex);
+    }
+
+    /** Called once an icon has been set. */
+    public void onSetIcon(int viewIndex, StatusBarIcon icon) {
+        StatusBarIconView view = (StatusBarIconView) mGroup.getChildAt(viewIndex);
+        view.set(icon);
+    }
+
+    /** Called once an icon holder has been set. */
+    public void onSetIconHolder(int viewIndex, StatusBarIconHolder holder) {
+        switch (holder.getType()) {
+            case TYPE_ICON:
+                onSetIcon(viewIndex, holder.getIcon());
+                return;
+            case TYPE_MOBILE_NEW:
+            case TYPE_WIFI_NEW:
+            case TYPE_BINDABLE:
+                // Nothing, the new icons update themselves
+                return;
+            default:
+                break;
+        }
+    }
+
+    @Override
+    public void dispatchDemoCommand(String command, Bundle args) {
+        if (!mDemoable) {
+            return;
+        }
+
+        mDemoStatusIcons.dispatchDemoCommand(command, args);
+    }
+
+    @Override
+    public void onDemoModeStarted() {
+        mIsInDemoMode = true;
+        if (mDemoStatusIcons == null) {
+            mDemoStatusIcons = createDemoStatusIcons();
+            mDemoStatusIcons.addModernWifiView(mWifiViewModel);
+        }
+        mDemoStatusIcons.onDemoModeStarted();
+    }
+
+    @Override
+    public void onDemoModeFinished() {
+        if (mDemoStatusIcons != null) {
+            mDemoStatusIcons.onDemoModeFinished();
+            exitDemoMode();
+            mIsInDemoMode = false;
+        }
+    }
+
+    protected void exitDemoMode() {
+        mDemoStatusIcons.remove();
+        mDemoStatusIcons = null;
+    }
+
+    protected DemoStatusIcons createDemoStatusIcons() {
+        return new DemoStatusIcons(
+                (LinearLayout) mGroup,
+                mMobileIconsViewModel,
+                mLocation,
+                mIconSize
+        );
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java
new file mode 100644
index 0000000..1ada30e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.ui;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.ArraySet;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.res.R;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
+
+import java.util.List;
+
+/** Interface controlling the icons shown in the status bar. */
+public interface StatusBarIconController {
+
+    /**
+     * When an icon is added with TAG_PRIMARY, it will be treated as the primary icon
+     * in that slot and not added as a sub slot.
+     */
+    int TAG_PRIMARY = 0;
+
+    /** */
+    void addIconGroup(IconManager iconManager);
+    /** */
+    void removeIconGroup(IconManager iconManager);
+
+    /** Refresh the state of an IconManager by recreating the views */
+    void refreshIconGroup(IconManager iconManager);
+
+    /**
+     * Adds or updates an icon that comes from an active tile service.
+     *
+     * If the icon is null, the icon will be removed.
+     */
+    void setIconFromTile(String slot, @Nullable StatusBarIcon icon);
+
+    /** Removes an icon that had come from an active tile service. */
+    void removeIconForTile(String slot);
+
+    /** Adds or updates an icon for the given slot for **internal system icons**. */
+    void setIcon(String slot, int resourceId, CharSequence contentDescription);
+
+    /**
+     * Sets up a wifi icon using the new data pipeline. No effect if the wifi icon has already been
+     * set up (inflated and added to the view hierarchy).
+     */
+    void setNewWifiIcon();
+
+    /**
+     * Notify this class that there is a new set of mobile icons to display, keyed off of this list
+     * of subIds. The icons will be added and bound to the mobile data pipeline via
+     * {@link com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconBinder}.
+     */
+    void setNewMobileIconSubIds(List<Integer> subIds);
+    /**
+     * Display the no calling & SMS icons.
+     */
+    void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states);
+
+    /**
+     * Display the no calling & SMS icons.
+     */
+    void setNoCallingIcons(String slot, List<CallIndicatorIconState> states);
+
+    /** Sets whether the icon in the given slot should be visible or not. */
+    void setIconVisibility(String slot, boolean b);
+
+    /**
+     * Sets the live region mode for the icon
+     *
+     * @param slot                    Icon slot to set region for
+     * @param accessibilityLiveRegion live region mode for the icon
+     * @see android.view.View#setAccessibilityLiveRegion(int)
+     */
+    void setIconAccessibilityLiveRegion(String slot, int accessibilityLiveRegion);
+
+    /**
+     * If you don't know what to pass for `tag`, either remove all icons for slot, or use
+     * TAG_PRIMARY to refer to the first icon at a given slot.
+     */
+    void removeIcon(String slot, int tag);
+
+    // TODO: See if we can rename this tunable name.
+    String ICON_HIDE_LIST = "icon_blacklist";
+
+    /** Reads the default hide list from config value unless hideListStr is provided. */
+    static ArraySet<String> getIconHideList(Context context, String hideListStr) {
+        ArraySet<String> ret = new ArraySet<>();
+        String[] hideList = hideListStr == null
+                ? context.getResources().getStringArray(R.array.config_statusBarIconsToExclude)
+                : hideListStr.split(",");
+        for (String slot : hideList) {
+            if (!TextUtils.isEmpty(slot)) {
+                ret.add(slot);
+            }
+        }
+        return ret;
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java
index 4f148f1..92d90af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java
@@ -11,12 +11,12 @@
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.statusbar.phone.ui;
 
-import static com.android.systemui.statusbar.phone.StatusBarIconList.Slot;
+import static com.android.systemui.statusbar.phone.ui.StatusBarIconList.Slot;
 
 import android.annotation.NonNull;
 import android.content.Context;
@@ -38,6 +38,7 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.StatusIconDisplayable;
+import com.android.systemui.statusbar.phone.StatusBarIconHolder;
 import com.android.systemui.statusbar.phone.StatusBarIconHolder.BindableIconHolder;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
@@ -459,9 +460,9 @@
         for (IconManager manager : mIconGroups) {
             if (manager.shouldLog()) {
                 ViewGroup group = manager.mGroup;
-                int N = group.getChildCount();
-                pw.println("  icon views: " + N);
-                for (int i = 0; i < N; i++) {
+                int n = group.getChildCount();
+                pw.println("  icon views: " + n);
+                for (int i = 0; i < n; i++) {
                     StatusIconDisplayable ic = (StatusIconDisplayable) group.getChildAt(i);
                     pw.println("    [" + i + "] icon=" + ic);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconList.java
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconList.java
index 565481a..724251c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconList.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.statusbar.phone.ui;
 
-import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
+import static com.android.systemui.statusbar.phone.ui.StatusBarIconController.TAG_PRIMARY;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.statusbar.phone.StatusBarIconHolder;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/TintedIconManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/TintedIconManager.java
new file mode 100644
index 0000000..e520148
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/TintedIconManager.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.ui;
+
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.statusbar.StatusIconDisplayable;
+import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
+import com.android.systemui.statusbar.phone.DemoStatusIcons;
+import com.android.systemui.statusbar.phone.StatusBarIconHolder;
+import com.android.systemui.statusbar.phone.StatusBarLocation;
+import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
+import com.android.systemui.statusbar.pipeline.wifi.ui.WifiUiAdapter;
+
+import javax.inject.Inject;
+
+/**
+ * Version of {@link IconManager} that can tint the icons to a particular color.
+ */
+public class TintedIconManager extends IconManager {
+    // The main tint, used as the foreground in non layer drawables
+    private int mColor;
+    // To be used as the main tint in drawables that wish to have a layer
+    private int mForegroundColor;
+
+    public TintedIconManager(
+            ViewGroup group,
+            StatusBarLocation location,
+            WifiUiAdapter wifiUiAdapter,
+            MobileUiAdapter mobileUiAdapter,
+            MobileContextProvider mobileContextProvider
+    ) {
+        super(group,
+                location,
+                wifiUiAdapter,
+                mobileUiAdapter,
+                mobileContextProvider);
+    }
+
+    @Override
+    protected void onIconAdded(int index, String slot, boolean blocked,
+            StatusBarIconHolder holder) {
+        StatusIconDisplayable view = addHolder(index, slot, blocked, holder);
+        view.setStaticDrawableColor(mColor, mForegroundColor);
+        view.setDecorColor(mColor);
+    }
+
+    /**
+     * Most icons are a single layer, and tintColor will be used as the tint in those cases.
+     * For icons that have a background, foregroundColor becomes the contrasting tint used
+     * for the foreground.
+     *
+     * @param tintColor       the main tint to use for the icons in the group
+     * @param foregroundColor used as the main tint for layer-ish drawables where tintColor is
+     *                        being used as the background
+     */
+    public void setTint(int tintColor, int foregroundColor) {
+        mColor = tintColor;
+        mForegroundColor = foregroundColor;
+
+        for (int i = 0; i < mGroup.getChildCount(); i++) {
+            View child = mGroup.getChildAt(i);
+            if (child instanceof StatusIconDisplayable icon) {
+                icon.setStaticDrawableColor(mColor, mForegroundColor);
+                icon.setDecorColor(mColor);
+            }
+        }
+
+        if (mDemoStatusIcons != null) {
+            mDemoStatusIcons.setColor(tintColor, foregroundColor);
+        }
+    }
+
+    @Override
+    protected DemoStatusIcons createDemoStatusIcons() {
+        DemoStatusIcons icons = super.createDemoStatusIcons();
+        icons.setColor(mColor, mForegroundColor);
+        return icons;
+    }
+
+    @SysUISingleton
+    public static class Factory {
+        private final WifiUiAdapter mWifiUiAdapter;
+        private final MobileContextProvider mMobileContextProvider;
+        private final MobileUiAdapter mMobileUiAdapter;
+
+        @Inject
+        public Factory(
+                WifiUiAdapter wifiUiAdapter,
+                MobileUiAdapter mobileUiAdapter,
+                MobileContextProvider mobileContextProvider
+        ) {
+            mWifiUiAdapter = wifiUiAdapter;
+            mMobileUiAdapter = mobileUiAdapter;
+            mMobileContextProvider = mobileContextProvider;
+        }
+
+        /** Creates a new {@link TintedIconManager} for the given view group and location. */
+        public TintedIconManager create(ViewGroup group, StatusBarLocation location) {
+            return new TintedIconManager(
+                    group,
+                    location,
+                    mWifiUiAdapter,
+                    mMobileUiAdapter,
+                    mMobileContextProvider);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
index 4f702d7..d4b2dbf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
@@ -102,6 +102,15 @@
         )
     }
 
+    fun logOnCarrierRoamingNtnModeChanged(active: Boolean) {
+        buffer.log(
+            TAG,
+            LogLevel.INFO,
+            { bool1 = active },
+            { "onCarrierRoamingNtnModeChanged: $bool1" }
+        )
+    }
+
     fun logOnDisplayInfoChanged(displayInfo: TelephonyDisplayInfo, subId: Int) {
         buffer.log(
             TAG,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
index b3885d2..6803a9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt
@@ -142,21 +142,33 @@
                 val callback =
                     object :
                         TelephonyCallback(),
-                        TelephonyCallback.ServiceStateListener,
-                        TelephonyCallback.SignalStrengthsListener,
-                        TelephonyCallback.DataConnectionStateListener,
-                        TelephonyCallback.DataActivityListener,
                         TelephonyCallback.CarrierNetworkListener,
+                        TelephonyCallback.CarrierRoamingNtnModeListener,
+                        TelephonyCallback.DataActivityListener,
+                        TelephonyCallback.DataConnectionStateListener,
+                        TelephonyCallback.DataEnabledListener,
                         TelephonyCallback.DisplayInfoListener,
-                        TelephonyCallback.DataEnabledListener {
-                        override fun onServiceStateChanged(serviceState: ServiceState) {
-                            logger.logOnServiceStateChanged(serviceState, subId)
-                            trySend(CallbackEvent.OnServiceStateChanged(serviceState))
+                        TelephonyCallback.ServiceStateListener,
+                        TelephonyCallback.SignalStrengthsListener {
+
+                        override fun onCarrierNetworkChange(active: Boolean) {
+                            logger.logOnCarrierNetworkChange(active, subId)
+                            trySend(CallbackEvent.OnCarrierNetworkChange(active))
                         }
 
-                        override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
-                            logger.logOnSignalStrengthsChanged(signalStrength, subId)
-                            trySend(CallbackEvent.OnSignalStrengthChanged(signalStrength))
+                        override fun onCarrierRoamingNtnModeChanged(active: Boolean) {
+                            logger.logOnCarrierRoamingNtnModeChanged(active)
+                            trySend(CallbackEvent.OnCarrierRoamingNtnModeChanged(active))
+                        }
+
+                        override fun onDataActivity(direction: Int) {
+                            logger.logOnDataActivity(direction, subId)
+                            trySend(CallbackEvent.OnDataActivity(direction))
+                        }
+
+                        override fun onDataEnabledChanged(enabled: Boolean, reason: Int) {
+                            logger.logOnDataEnabledChanged(enabled, subId)
+                            trySend(CallbackEvent.OnDataEnabledChanged(enabled))
                         }
 
                         override fun onDataConnectionStateChanged(
@@ -167,16 +179,6 @@
                             trySend(CallbackEvent.OnDataConnectionStateChanged(dataState))
                         }
 
-                        override fun onDataActivity(direction: Int) {
-                            logger.logOnDataActivity(direction, subId)
-                            trySend(CallbackEvent.OnDataActivity(direction))
-                        }
-
-                        override fun onCarrierNetworkChange(active: Boolean) {
-                            logger.logOnCarrierNetworkChange(active, subId)
-                            trySend(CallbackEvent.OnCarrierNetworkChange(active))
-                        }
-
                         override fun onDisplayInfoChanged(
                             telephonyDisplayInfo: TelephonyDisplayInfo
                         ) {
@@ -184,9 +186,14 @@
                             trySend(CallbackEvent.OnDisplayInfoChanged(telephonyDisplayInfo))
                         }
 
-                        override fun onDataEnabledChanged(enabled: Boolean, reason: Int) {
-                            logger.logOnDataEnabledChanged(enabled, subId)
-                            trySend(CallbackEvent.OnDataEnabledChanged(enabled))
+                        override fun onServiceStateChanged(serviceState: ServiceState) {
+                            logger.logOnServiceStateChanged(serviceState, subId)
+                            trySend(CallbackEvent.OnServiceStateChanged(serviceState))
+                        }
+
+                        override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
+                            logger.logOnSignalStrengthsChanged(signalStrength, subId)
+                            trySend(CallbackEvent.OnSignalStrengthChanged(signalStrength))
                         }
                     }
                 telephonyManager.registerTelephonyCallback(bgDispatcher.asExecutor(), callback)
@@ -229,8 +236,8 @@
 
     override val isNonTerrestrial =
         callbackEvents
-            .mapNotNull { it.onServiceStateChanged }
-            .map { it.serviceState.isUsingNonTerrestrialNetwork }
+            .mapNotNull { it.onCarrierRoamingNtnModeChanged }
+            .map { it.active }
             .stateIn(scope, SharingStarted.WhileSubscribed(), false)
 
     override val isGsm =
@@ -502,6 +509,8 @@
 sealed interface CallbackEvent {
     data class OnCarrierNetworkChange(val active: Boolean) : CallbackEvent
 
+    data class OnCarrierRoamingNtnModeChanged(val active: Boolean) : CallbackEvent
+
     data class OnDataActivity(val direction: Int) : CallbackEvent
 
     data class OnDataConnectionStateChanged(val dataState: Int) : CallbackEvent
@@ -522,6 +531,7 @@
 data class TelephonyCallbackState(
     val onDataActivity: CallbackEvent.OnDataActivity? = null,
     val onCarrierNetworkChange: CallbackEvent.OnCarrierNetworkChange? = null,
+    val onCarrierRoamingNtnModeChanged: CallbackEvent.OnCarrierRoamingNtnModeChanged? = null,
     val onDataConnectionStateChanged: CallbackEvent.OnDataConnectionStateChanged? = null,
     val onDataEnabledChanged: CallbackEvent.OnDataEnabledChanged? = null,
     val onDisplayInfoChanged: CallbackEvent.OnDisplayInfoChanged? = null,
@@ -531,6 +541,9 @@
     fun applyEvent(event: CallbackEvent): TelephonyCallbackState {
         return when (event) {
             is CallbackEvent.OnCarrierNetworkChange -> copy(onCarrierNetworkChange = event)
+            is CallbackEvent.OnCarrierRoamingNtnModeChanged -> {
+                copy(onCarrierRoamingNtnModeChanged = event)
+            }
             is CallbackEvent.OnDataActivity -> copy(onDataActivity = event)
             is CallbackEvent.OnDataConnectionStateChanged ->
                 copy(onDataConnectionStateChanged = event)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
index 02e50a0..5a49f8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileUiAdapter.kt
@@ -20,7 +20,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.shade.carrier.ShadeCarrierGroupController
-import com.android.systemui.statusbar.phone.StatusBarIconController
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController
 import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
 import java.io.PrintWriter
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconsBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconsBinder.kt
index e7d5ee2..fc0ba13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconsBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/binder/MobileIconsBinder.kt
@@ -20,10 +20,9 @@
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager
+import com.android.systemui.statusbar.phone.ui.IconManager
 import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.launch
 
 object MobileIconsBinder {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt
index 4227f9e..1a55f7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt
@@ -31,12 +31,12 @@
 import androidx.annotation.ArrayRes
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.Dumpable
-import com.android.systemui.res.R
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.phone.StatusBarIconController
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController
 import com.android.systemui.statusbar.pipeline.shared.ConnectivityInputLogger
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
 import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index 20e44e7..885abca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -322,11 +322,6 @@
                 wifiManager.registerTrafficStateCallback(mainExecutor, callback)
                 awaitClose { wifiManager.unregisterTrafficStateCallback(callback) }
             }
-            .logDiffsForTable(
-                tableLogger,
-                columnPrefix = ACTIVITY_PREFIX,
-                initialValue = ACTIVITY_DEFAULT,
-            )
             .stateIn(
                 scope,
                 started = SharingStarted.WhileSubscribed(),
@@ -441,7 +436,6 @@
 
         private const val WIFI_STATE_DEFAULT = WifiManager.WIFI_STATE_DISABLED
 
-        private const val ACTIVITY_PREFIX = "wifiActivity"
         val ACTIVITY_DEFAULT = DataActivityModel(hasActivityIn = false, hasActivityOut = false)
 
         private const val TAG = "WifiTrackerLibInputLog"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt
index 7a60d96..2800c94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/WifiUiAdapter.kt
@@ -21,14 +21,13 @@
 import androidx.lifecycle.repeatOnLifecycle
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.statusbar.phone.StatusBarIconController
 import com.android.systemui.statusbar.phone.StatusBarLocation
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController
 import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel.Companion.viewModelForLocation
 import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel
 import javax.inject.Inject
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.launch
 
 /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 149c8fa..64bdf60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -48,7 +48,6 @@
 
 import javax.inject.Inject;
 
-
 /** Platform implementation of the cast controller. **/
 @SysUISingleton
 public class CastControllerImpl implements CastController {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 20d1fff..ccd7560 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -48,14 +48,14 @@
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.FontSizeUtils;
-import com.android.systemui.res.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.demomode.DemoModeCommandReceiver;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index 74e02d7..7e6e00e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -29,8 +29,8 @@
 import android.widget.TextView;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.res.R;
 
 import java.util.Date;
 import java.util.Locale;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 4b97197..d0cc32b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -32,11 +32,11 @@
 import androidx.annotation.NonNull;
 
 import com.android.internal.util.ConcurrentUtils;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 
 import java.io.PrintWriter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
index ad2b070..b07aa81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java
@@ -18,7 +18,6 @@
 
 import android.app.IActivityTaskManager;
 
-import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.policy.KeyguardStateController.Callback;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java
index 012408e..3eeb59d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserDetailItemView.java
@@ -26,8 +26,8 @@
 
 import com.android.app.animation.Interpolators;
 import com.android.keyguard.KeyguardConstants;
-import com.android.systemui.res.R;
 import com.android.systemui.qs.tiles.UserDetailItemView;
+import com.android.systemui.res.R;
 
 /**
  * Displays a user on the keyguard user switcher.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt
index db4e605d..08f973b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PolicyModule.kt
@@ -88,6 +88,7 @@
         const val WORK_MODE_TILE_SPEC = "work"
         const val CAMERA_TOGGLE_TILE_SPEC = "cameratoggle"
         const val MIC_TOGGLE_TILE_SPEC = "mictoggle"
+        const val DND_TILE_SPEC = "dnd"
 
         /** Inject flashlight config */
         @Provides
@@ -136,10 +137,7 @@
                 instanceId = uiEventLogger.getNewInstanceId(),
                 policy =
                     QSTilePolicy.Restricted(
-                        listOf(
-                            DISALLOW_SHARE_LOCATION,
-                            DISALLOW_CONFIG_LOCATION
-                        )
+                        listOf(DISALLOW_SHARE_LOCATION, DISALLOW_CONFIG_LOCATION)
                     )
             )
 
@@ -321,6 +319,21 @@
                 stateInteractor.create(MICROPHONE),
                 mapper.create(SensorPrivacyTileResources.MicrophonePrivacyTileResources),
             )
+
+        /** Inject microphone toggle config */
+        @Provides
+        @IntoMap
+        @StringKey(DND_TILE_SPEC)
+        fun provideDndTileConfig(uiEventLogger: QsEventLogger): QSTileConfig =
+            QSTileConfig(
+                tileSpec = TileSpec.create(DND_TILE_SPEC),
+                uiConfig =
+                    QSTileUIConfig.Resource(
+                        iconRes = R.drawable.qs_dnd_icon_off,
+                        labelRes = R.string.quick_settings_dnd_label,
+                    ),
+                instanceId = uiEventLogger.getNewInstanceId(),
+            )
     }
 
     /** Inject FlashlightTile into tileMap in QSModule */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index bf33473..8daa518 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -19,16 +19,15 @@
 import android.app.RemoteInput;
 import android.content.Context;
 import android.content.res.Resources;
-import android.os.Handler;
 import android.provider.DeviceConfig;
 import android.text.TextUtils;
 import android.util.KeyValueListParser;
 import android.util.Log;
 
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
 import com.android.systemui.util.DeviceConfigProxy;
 
 import java.util.concurrent.Executor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
index 2ed9d15..712bab0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
@@ -36,9 +36,9 @@
 
 import com.android.internal.util.UserIcons;
 import com.android.settingslib.drawable.UserIconDrawable;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeModule.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeModule.java
index e78eba4..0cd917f 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeModule.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeModule.java
@@ -18,15 +18,15 @@
 
 import android.content.res.Resources;
 
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
 import com.android.systemui.util.concurrency.SysUIConcurrencyModule;
 
-import javax.inject.Named;
-
 import dagger.Module;
 import dagger.Provides;
 
+import javax.inject.Named;
+
 /** */
 @Module(includes = {SysUIConcurrencyModule.class})
 public class ThemeModule {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
index b71aafd..77fcd25 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java
@@ -27,7 +27,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 
 public class BatteryPreference extends DropDownPreference implements TunerService.Tunable {
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
index c92d7bb..e94d8ea 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/ClockPreference.java
@@ -21,7 +21,7 @@
 import androidx.preference.DropDownPreference;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.policy.Clock;
 
 public class ClockPreference extends DropDownPreference implements TunerService.Tunable {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
index a43524a..68918ef 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -29,10 +29,10 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.res.R;
 import com.android.systemui.demomode.DemoMode;
 import com.android.systemui.demomode.DemoModeAvailabilityTracker;
 import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.res.R;
 import com.android.systemui.util.settings.GlobalSettings;
 
 public class DemoModeFragment extends PreferenceFragment implements OnPreferenceChangeListener {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
index 799e5af..ab2a7c7 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java
@@ -41,8 +41,8 @@
 import androidx.recyclerview.widget.RecyclerView.ViewHolder;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
 import com.android.systemui.statusbar.phone.ExpandableIndicator;
 import com.android.systemui.statusbar.policy.ExtensionController.TunerFactory;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
index 7635a84..c7b848c 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java
@@ -36,9 +36,9 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.PluginEnablerImpl;
 import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.res.R;
 import com.android.systemui.shared.plugins.PluginActionManager;
 import com.android.systemui.shared.plugins.PluginEnabler;
 import com.android.systemui.shared.plugins.PluginPrefs;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
index 20ce230..50ed3ef 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/RadioListPreference.java
@@ -29,8 +29,8 @@
 
 import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
 import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.res.R;
 
 import java.util.Objects;
 
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index cc0050b..2f6fa51 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -27,7 +27,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Dependency;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.tuner.TunerService.Tunable;
 
 import java.util.Set;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 14d7281..2135817 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -30,9 +30,9 @@
 import androidx.preference.PreferenceScreen;
 
 import com.android.systemui.Dependency;
-import com.android.systemui.res.R;
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.res.R;
 import com.android.systemui.util.settings.GlobalSettings;
 
 import javax.inject.Inject;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 550a65c..05ee35b 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -38,14 +38,14 @@
 
 import com.android.internal.util.ArrayUtils;
 import com.android.systemui.DejankUtils;
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.qs.QSHost;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.util.leak.LeakDetector;
 
 import dagger.Lazy;
@@ -56,7 +56,6 @@
 
 import javax.inject.Inject;
 
-
 /**
  * @deprecated Don't use this class to listen to Secure Settings. Use {@code SecureSettings} instead
  * or {@code SettingsObserver} to be able to specify the handler.
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index e4f1c87..42563fd 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -39,8 +39,8 @@
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
-import com.android.systemui.res.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.res.R;
 
 import javax.inject.Inject;
 
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java
index ea871be..64e35d9 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java
@@ -34,8 +34,8 @@
 
 import com.android.internal.app.AlertActivity;
 import com.android.internal.app.AlertController;
-import com.android.systemui.res.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.res.R;
 
 import javax.inject.Inject;
 
diff --git a/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java b/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java
index 562feb2e..56b46624 100644
--- a/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/user/CreateUserActivity.java
@@ -33,8 +33,8 @@
 
 import com.android.internal.logging.UiEventLogger;
 import com.android.settingslib.users.CreateUserDialogController;
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.res.R;
 
 import javax.inject.Inject;
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/annotations/WeaklyReferencedCallback.java b/packages/SystemUI/src/com/android/systemui/util/annotations/WeaklyReferencedCallback.java
index 855bba6..574e331 100644
--- a/packages/SystemUI/src/com/android/systemui/util/annotations/WeaklyReferencedCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/util/annotations/WeaklyReferencedCallback.java
@@ -22,7 +22,6 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
-
 /**
  * Descriptive annotation for clearly tagging callback types that are weakly
  * referenced during registration.
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java
index e40d276..ecf1165 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java
@@ -23,15 +23,15 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 
+import dagger.Binds;
+import dagger.Module;
+import dagger.Provides;
+
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 
 import javax.inject.Singleton;
 
-import dagger.Binds;
-import dagger.Module;
-import dagger.Provides;
-
 /**
  * Dagger Module for classes found within the concurrent package.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Parallel.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Parallel.kt
new file mode 100644
index 0000000..a47a2d6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Parallel.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.util.kotlin
+
+import kotlinx.coroutines.CoroutineStart
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.coroutineScope
+
+/** Like [Iterable.flatMap] but executes each [transform] invocation in a separate coroutine. */
+suspend fun <A, B> Iterable<A>.flatMapParallel(transform: suspend (A) -> Iterable<B>): List<B> =
+    mapParallel(transform).flatten()
+
+/** Like [Iterable.mapNotNull] but executes each [transform] invocation in a separate coroutine. */
+suspend fun <A, B> Iterable<A>.mapNotNullParallel(transform: suspend (A) -> B?): List<B> =
+    mapParallel(transform).filterNotNull()
+
+/** Like [Iterable.map] but executes each [transform] invocation in a separate coroutine. */
+suspend fun <A, B> Iterable<A>.mapParallel(transform: suspend (A) -> B): List<B> = coroutineScope {
+    map { async(start = CoroutineStart.LAZY) { transform(it) } }.awaitAll()
+}
+
+/** Like [mapValues] but executes each [transform] invocation in a separate coroutine. */
+suspend fun <K, A, B> Map<K, A>.mapValuesParallel(
+    transform: suspend (Map.Entry<K, A>) -> B
+): Map<K, B> = entries.mapParallel { it.key to transform(it) }.toMap()
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java b/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java
index 7934ab1..a7b6de2 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/SensorModule.java
@@ -24,19 +24,19 @@
 
 import androidx.annotation.NonNull;
 
-import com.android.systemui.res.R;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
 import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
 
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Dagger module for Sensor related classes.
  */
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index cd82e1d..c69fb66 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -137,13 +137,13 @@
 import com.android.systemui.volume.domain.interactor.VolumePanelNavigationInteractor;
 import com.android.systemui.volume.ui.navigation.VolumeNavigator;
 
+import dagger.Lazy;
+
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Consumer;
 
-import dagger.Lazy;
-
 /**
  * Visual presentation of the volume dialog.
  *
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java
index 6050387..3785f13 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java
@@ -51,8 +51,8 @@
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.settingslib.media.MediaOutputConstants;
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 
 import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeToolTipView.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeToolTipView.java
index 2143771..44382b6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeToolTipView.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeToolTipView.java
@@ -28,8 +28,8 @@
 
 import androidx.core.content.ContextCompat;
 
-import com.android.systemui.res.R;
 import com.android.systemui.recents.TriangleShape;
+import com.android.systemui.res.R;
 
 /**
  * Tool tip view that draws an arrow that points to the volume dialog.
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/dagger/WalletModule.java b/packages/SystemUI/src/com/android/systemui/wallet/dagger/WalletModule.java
index efba3e5..4841c78 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/dagger/WalletModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/dagger/WalletModule.java
@@ -17,6 +17,7 @@
 package com.android.systemui.wallet.dagger;
 
 import android.app.Activity;
+import android.app.Service;
 import android.content.Context;
 import android.service.quickaccesswallet.QuickAccessWalletClient;
 
@@ -24,10 +25,9 @@
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.qs.tiles.QuickAccessWalletTile;
+import com.android.systemui.wallet.controller.WalletContextualLocationsService;
 import com.android.systemui.wallet.ui.WalletActivity;
 
-import java.util.concurrent.Executor;
-
 import dagger.Binds;
 import dagger.Module;
 import dagger.Provides;
@@ -35,8 +35,7 @@
 import dagger.multibindings.IntoMap;
 import dagger.multibindings.StringKey;
 
-import android.app.Service;
-import com.android.systemui.wallet.controller.WalletContextualLocationsService;
+import java.util.concurrent.Executor;
 
 /**
  * Module for injecting classes in Wallet.
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
index d21ccc9..53e6b4f 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
@@ -43,9 +43,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.UiEventLogger;
 import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java b/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
index d37dfb4..3c9259c 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractor.java
@@ -51,7 +51,7 @@
     private Bitmap mMiniBitmap;
 
     @VisibleForTesting
-    static final int SMALL_SIDE = 128;
+    static final int MINI_BITMAP_MAX_AREA = 112 * 112;
 
     private static final String TAG = WallpaperLocalColorExtractor.class.getSimpleName();
     private static final @NonNull RectF LOCAL_COLOR_BOUNDS =
@@ -326,12 +326,12 @@
 
     private Bitmap createMiniBitmap(@NonNull Bitmap bitmap) {
         Trace.beginSection("WallpaperLocalColorExtractor#createMiniBitmap");
-        // if both sides of the image are larger than SMALL_SIDE, downscale the bitmap.
-        int smallestSide = Math.min(bitmap.getWidth(), bitmap.getHeight());
-        float scale = Math.min(1.0f, (float) SMALL_SIDE / smallestSide);
+        // if the area of the image is greater than MINI_BITMAP_MAX_AREA, downscale the bitmap.
+        int area = bitmap.getWidth() * bitmap.getHeight();
+        double scale = Math.min(1, Math.sqrt((double) MINI_BITMAP_MAX_AREA / area));
         Bitmap result = createMiniBitmap(bitmap,
-                (int) (scale * bitmap.getWidth()),
-                (int) (scale * bitmap.getHeight()));
+                Math.max(1, (int) (scale * bitmap.getWidth())),
+                Math.max(1, (int) (scale * bitmap.getHeight())));
         Trace.endSection();
         return result;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
index 1ba269e..041b6f9 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
@@ -28,7 +28,9 @@
 import com.android.systemui.user.data.model.SelectedUserModel
 import com.android.systemui.user.data.model.SelectionStatus
 import com.android.systemui.user.data.repository.UserRepository
+import com.android.systemui.utils.coroutines.flow.mapLatestConflated
 import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -40,6 +42,7 @@
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.withContext
 
 /** A repository storing information about the current wallpaper. */
 interface WallpaperRepository {
@@ -55,6 +58,7 @@
 @Inject
 constructor(
     @Background scope: CoroutineScope,
+    @Background private val bgDispatcher: CoroutineDispatcher,
     broadcastDispatcher: BroadcastDispatcher,
     userRepository: UserRepository,
     private val wallpaperManager: WallpaperManager,
@@ -87,14 +91,15 @@
         if (!wallpaperManager.isWallpaperSupported || !deviceSupportsAodWallpaper) {
             MutableStateFlow(null).asStateFlow()
         } else {
-            combine(wallpaperChanged, selectedUser) { _, selectedUser ->
-                    getWallpaper(selectedUser)
-                }
+            combine(wallpaperChanged, selectedUser, ::Pair)
+                .mapLatestConflated { (_, selectedUser) -> getWallpaper(selectedUser) }
                 .stateIn(
                     scope,
                     // Always be listening for wallpaper changes.
                     SharingStarted.Eagerly,
-                    initialValue = getWallpaper(userRepository.selectedUser.value),
+                    // The initial value is null, but it should get updated pretty quickly because
+                    // the `combine` should immediately kick off a fetch.
+                    initialValue = null,
                 )
         }
 
@@ -111,7 +116,9 @@
                 initialValue = wallpaperInfo.value?.supportsAmbientMode() == true,
             )
 
-    private fun getWallpaper(selectedUser: SelectedUserModel): WallpaperInfo? {
-        return wallpaperManager.getWallpaperInfoForUser(selectedUser.userInfo.id)
+    private suspend fun getWallpaper(selectedUser: SelectedUserModel): WallpaperInfo? {
+        return withContext(bgDispatcher) {
+            wallpaperManager.getWallpaperInfoForUser(selectedUser.userInfo.id)
+        }
     }
 }
diff --git a/packages/SystemUI/tests/robolectric/src/com/android/systemui/robotests/SysuiResourceLoadingTest.java b/packages/SystemUI/tests/robolectric/src/com/android/systemui/robotests/SysuiResourceLoadingTest.java
index 205168e..a48d179 100644
--- a/packages/SystemUI/tests/robolectric/src/com/android/systemui/robotests/SysuiResourceLoadingTest.java
+++ b/packages/SystemUI/tests/robolectric/src/com/android/systemui/robotests/SysuiResourceLoadingTest.java
@@ -16,9 +16,11 @@
 
 package com.android.systemui.robotests;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
-import static com.google.common.truth.Truth.assertThat;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
index 11d31c6..8c4179d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
@@ -69,6 +69,8 @@
 import com.android.systemui.util.kotlin.JavaAdapter;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -81,8 +83,6 @@
 import java.util.HashMap;
 import java.util.List;
 
-import kotlinx.coroutines.test.TestScope;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class CarrierTextManagerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
index 8401e67..edf29c5 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockAccessibilityDelegateTest.java
@@ -27,8 +27,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
index f1dfdf4..07504c7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerBaseTest.java
@@ -20,8 +20,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
-
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.widget.FrameLayout;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index d354fa2..d6f0ef8 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -19,6 +19,7 @@
 import static android.app.StatusBarManager.SESSION_KEYGUARD;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT;
 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
 import static android.hardware.biometrics.SensorProperties.STRENGTH_CONVENIENCE;
@@ -82,7 +83,6 @@
 import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.ComponentInfoInternal;
 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
-import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorProperties;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
@@ -2276,8 +2276,7 @@
     private void faceAuthLockOut() {
         when(mFaceAuthInteractor.isLockedOut()).thenReturn(true);
         mFaceAuthenticationListener.getValue().onAuthenticationStatusChanged(
-                new ErrorFaceAuthenticationStatus(FaceManager.FACE_ERROR_LOCKOUT_PERMANENT, "",
-                        0L));
+                new ErrorFaceAuthenticationStatus(FACE_ERROR_LOCKOUT_PERMANENT, "", 0L));
     }
 
     private void statusBarShadeIsNotLocked() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationGestureDetectorTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationGestureDetectorTest.java
index 36ae3c0..ad02179 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationGestureDetectorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationGestureDetectorTest.java
@@ -44,7 +44,6 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class MagnificationGestureDetectorTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapterTest.java
index 403385f..630db62 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityTargetAdapterTest.java
@@ -28,9 +28,9 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.accessibility.dialog.AccessibilityTarget;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.accessibility.floatingmenu.AccessibilityTargetAdapter.ViewHolder;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpanTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpanTest.java
index 43ebeee..4b87588 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpanTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpanTest.java
@@ -26,8 +26,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
index 1e3b556..d01d57e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
@@ -24,26 +24,35 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.hardware.display.DisplayManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
 import android.testing.AndroidTestingRunner;
-import android.util.Pair;
+import android.testing.TestableLooper;
 import android.view.GestureDetector;
 import android.view.IWindowManager;
 import android.view.InputEvent;
 import android.view.MotionEvent;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
 
-import androidx.lifecycle.DefaultLifecycleObserver;
+import androidx.annotation.NonNull;
 import androidx.lifecycle.Lifecycle;
-import androidx.lifecycle.LifecycleObserver;
 import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
 import androidx.test.filters.SmallTest;
 
+import com.android.systemui.Flags;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.ambient.touch.dagger.InputSessionComponent;
+import com.android.systemui.kosmos.KosmosJavaAdapter;
 import com.android.systemui.shared.system.InputChannelCompat;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.display.DisplayHelper;
@@ -67,31 +76,58 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
 public class TouchMonitorTest extends SysuiTestCase {
+    private KosmosJavaAdapter mKosmos;
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
+        mKosmos = new KosmosJavaAdapter(this);
+    }
+
+    private static class SimpleLifecycleOwner implements LifecycleOwner {
+        LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
+        @NonNull
+        @Override
+        public Lifecycle getLifecycle() {
+            return mLifecycle;
+        }
+
+        public void setState(Lifecycle.State state) {
+            mLifecycle.setCurrentState(state);
+        }
     }
 
     private static class Environment {
         private final InputSessionComponent.Factory mInputFactory;
         private final InputSession mInputSession;
-        private final Lifecycle mLifecycle;
-        private final LifecycleOwner mLifecycleOwner;
+        private final SimpleLifecycleOwner mLifecycleOwner;
+
+        private final LifecycleRegistry mLifecycleRegistry;
         private final TouchMonitor mMonitor;
-        private final DefaultLifecycleObserver mLifecycleObserver;
         private final InputChannelCompat.InputEventListener mEventListener;
         private final GestureDetector.OnGestureListener mGestureListener;
         private final DisplayHelper mDisplayHelper;
+        private final DisplayManager mDisplayManager;
+        private final WindowManager mWindowManager;
+        private final WindowMetrics mWindowMetrics;
         private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
         private final FakeExecutor mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());
+
         private final Rect mDisplayBounds = Mockito.mock(Rect.class);
         private final IWindowManager mIWindowManager;
 
-        Environment(Set<TouchHandler> handlers) {
-            mLifecycle = Mockito.mock(Lifecycle.class);
-            mLifecycleOwner = Mockito.mock(LifecycleOwner.class);
+        private final KosmosJavaAdapter mKosmos;
+
+
+        Environment(Set<TouchHandler> handlers, KosmosJavaAdapter kosmos) {
+            mLifecycleOwner = new SimpleLifecycleOwner();
+            mLifecycleRegistry = spy(new LifecycleRegistry(mLifecycleOwner));
+
             mIWindowManager = Mockito.mock(IWindowManager.class);
+            mDisplayManager = Mockito.mock(DisplayManager.class);
+            mWindowManager = Mockito.mock(WindowManager.class);
+            mKosmos = kosmos;
 
             mInputFactory = Mockito.mock(InputSessionComponent.Factory.class);
             final InputSessionComponent inputComponent = Mockito.mock(InputSessionComponent.class);
@@ -104,18 +140,16 @@
             mDisplayHelper = Mockito.mock(DisplayHelper.class);
             when(mDisplayHelper.getMaxBounds(anyInt(), anyInt()))
                     .thenReturn(mDisplayBounds);
-            mMonitor = new TouchMonitor(mExecutor, mBackgroundExecutor,
-                    mLifecycle, mInputFactory, mDisplayHelper, handlers, mIWindowManager, 0);
+
+            mWindowMetrics = Mockito.mock(WindowMetrics.class);
+            when(mWindowMetrics.getBounds()).thenReturn(mDisplayBounds);
+            when(mWindowManager.getMaximumWindowMetrics()).thenReturn(mWindowMetrics);
+            mMonitor = new TouchMonitor(mExecutor, mBackgroundExecutor, mLifecycleRegistry,
+                    mInputFactory, mDisplayHelper, mKosmos.getConfigurationInteractor(),
+                    handlers, mIWindowManager,  0);
             mMonitor.init();
 
-            final ArgumentCaptor<LifecycleObserver> lifecycleObserverCaptor =
-                    ArgumentCaptor.forClass(LifecycleObserver.class);
-            verify(mLifecycle).addObserver(lifecycleObserverCaptor.capture());
-            assertThat(lifecycleObserverCaptor.getValue() instanceof DefaultLifecycleObserver)
-                    .isTrue();
-            mLifecycleObserver = (DefaultLifecycleObserver) lifecycleObserverCaptor.getValue();
-
-            updateLifecycle(observer -> observer.first.onResume(observer.second));
+            updateLifecycle(Lifecycle.State.RESUMED);
 
             // Capture creation request.
             final ArgumentCaptor<InputChannelCompat.InputEventListener> inputEventListenerCaptor =
@@ -145,8 +179,8 @@
             listenerConsumer.accept(mGestureListener);
         }
 
-        void updateLifecycle(Consumer<Pair<DefaultLifecycleObserver, LifecycleOwner>> consumer) {
-            consumer.accept(Pair.create(mLifecycleObserver, mLifecycleOwner));
+        void updateLifecycle(Lifecycle.State state) {
+            mLifecycleRegistry.setCurrentState(state);
         }
 
         void verifyInputSessionDispose() {
@@ -156,10 +190,33 @@
     }
 
     @Test
+    @EnableFlags(Flags.FLAG_AMBIENT_TOUCH_MONITOR_LISTEN_TO_DISPLAY_CHANGES)
+    public void testConfigurationListenerUpdatesBounds() {
+        final TouchHandler touchHandler = createTouchHandler();
+        final Environment environment = new Environment(Stream.of(touchHandler)
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
+        ArgumentCaptor<DisplayManager.DisplayListener> listenerCaptor =
+                ArgumentCaptor.forClass(DisplayManager.DisplayListener.class);
+        final Rect testRect = new Rect(0, 0, 2, 2);
+        final Configuration configuration = new Configuration();
+        configuration.windowConfiguration.setMaxBounds(testRect);
+
+        mKosmos.getConfigurationRepository().onConfigurationChange(configuration);
+        final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
+        when(initialEvent.getX()).thenReturn(0.0f);
+        when(initialEvent.getY()).thenReturn(0.0f);
+        environment.publishInputEvent(initialEvent);
+
+        // Verify display bounds passed into TouchHandler#getTouchInitiationRegion
+        verify(touchHandler).getTouchInitiationRegion(eq(testRect), any(), any());
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_AMBIENT_TOUCH_MONITOR_LISTEN_TO_DISPLAY_CHANGES)
     public void testReportedDisplayBounds() {
         final TouchHandler touchHandler = createTouchHandler();
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
         when(initialEvent.getX()).thenReturn(0.0f);
@@ -190,7 +247,7 @@
         }).when(touchHandler).getTouchInitiationRegion(any(), any(), any());
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         // Ensure touch outside specified region is not delivered.
         final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
@@ -219,7 +276,7 @@
         }).when(touchHandler).getTouchInitiationRegion(any(), any(), any());
 
         final Environment environment = new Environment(Stream.of(touchHandler, unzonedTouchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         // Ensure touch outside specified region is delivered to unzoned touch handler.
         final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
@@ -261,7 +318,7 @@
         when(touchHandler.isEnabled()).thenReturn(false);
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
         final MotionEvent initialEvent = Mockito.mock(MotionEvent.class);
         when(initialEvent.getX()).thenReturn(5.0f);
         when(initialEvent.getY()).thenReturn(5.0f);
@@ -277,7 +334,7 @@
         final TouchHandler touchHandler = createTouchHandler();
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -297,7 +354,7 @@
         final TouchHandler touchHandler = createTouchHandler();
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -321,7 +378,7 @@
         final TouchHandler touchHandler = createTouchHandler();
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -340,7 +397,7 @@
         final TouchHandler touchHandler = createTouchHandler();
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -365,7 +422,7 @@
         when(touchHandler2.isEnabled()).thenReturn(true);
 
         final Environment environment = new Environment(Stream.of(touchHandler, touchHandler2)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -389,7 +446,7 @@
         final TouchHandler touchHandler = createTouchHandler();
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -435,7 +492,7 @@
                 Mockito.mock(TouchHandler.TouchSession.Callback.class);
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -453,11 +510,9 @@
         final TouchHandler touchHandler = createTouchHandler();
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
-        environment.updateLifecycle(observerOwnerPair -> {
-            observerOwnerPair.first.onPause(observerOwnerPair.second);
-        });
+        environment.updateLifecycle(Lifecycle.State.STARTED);
 
         environment.verifyInputSessionDispose();
     }
@@ -467,7 +522,7 @@
         final TouchHandler touchHandler = createTouchHandler();
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -486,9 +541,7 @@
 
         verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
 
-        environment.updateLifecycle(observerOwnerPair -> {
-            observerOwnerPair.first.onPause(observerOwnerPair.second);
-        });
+        environment.updateLifecycle(Lifecycle.State.STARTED);
 
         verify(environment.mInputSession, never()).dispose();
 
@@ -505,7 +558,7 @@
         final TouchHandler touchHandler = createTouchHandler();
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -524,9 +577,7 @@
 
         verify(touchHandler).onSessionStart(touchSessionArgumentCaptor.capture());
 
-        environment.updateLifecycle(observerOwnerPair -> {
-            observerOwnerPair.first.onDestroy(observerOwnerPair.second);
-        });
+        environment.updateLifecycle(Lifecycle.State.DESTROYED);
 
         // Check to make sure the input session is now disposed.
         environment.verifyInputSessionDispose();
@@ -538,7 +589,7 @@
         final TouchHandler touchHandler1 = createTouchHandler();
         final TouchHandler touchHandler2 = createTouchHandler();
         final Environment environment = new Environment(Stream.of(touchHandler1, touchHandler2)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -574,7 +625,7 @@
                 Mockito.mock(TouchHandler.TouchSession.Callback.class);
 
         final Environment environment = new Environment(Stream.of(touchHandler)
-                .collect(Collectors.toCollection(HashSet::new)));
+                .collect(Collectors.toCollection(HashSet::new)), mKosmos);
 
         final InputEvent initialEvent = Mockito.mock(InputEvent.class);
         environment.publishInputEvent(initialEvent);
@@ -584,9 +635,7 @@
 
         environment.executeAll();
 
-        environment.updateLifecycle(observerOwnerPair -> {
-            observerOwnerPair.first.onDestroy(observerOwnerPair.second);
-        });
+        environment.updateLifecycle(Lifecycle.State.DESTROYED);
 
         environment.executeAll();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/assist/ui/DisplayUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/assist/ui/DisplayUtilsTest.java
index 957443a..4d582ab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/assist/ui/DisplayUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/assist/ui/DisplayUtilsTest.java
@@ -25,8 +25,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
index 323f15a..14eff2f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewControllerTest.java
@@ -33,9 +33,9 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.flags.FakeFeatureFlags;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.StatusBarLocation;
 import com.android.systemui.statusbar.policy.BatteryController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
index 01d9df8..ec2b104 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
@@ -17,12 +17,10 @@
 package com.android.systemui.biometrics.ui.binder
 
 import android.animation.Animator
-import android.app.ActivityTaskManager
 import android.graphics.Rect
 import android.hardware.biometrics.SensorLocationInternal
 import android.hardware.display.DisplayManager
 import android.hardware.display.DisplayManagerGlobal
-import android.os.Handler
 import android.testing.TestableLooper
 import android.view.Display
 import android.view.DisplayInfo
@@ -32,67 +30,31 @@
 import android.view.WindowInsets
 import android.view.WindowManager
 import android.view.WindowMetrics
+import android.view.layoutInflater
+import android.view.windowManager
 import androidx.test.filters.SmallTest
 import com.airbnb.lottie.LottieAnimationView
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.keyguardUpdateMonitor
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider
-import com.android.systemui.biometrics.FpsUnlockTracker
-import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
-import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
-import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
-import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractorImpl
-import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
-import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
+import com.android.systemui.biometrics.data.repository.biometricStatusRepository
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
 import com.android.systemui.biometrics.shared.model.AuthenticationReason
 import com.android.systemui.biometrics.shared.model.DisplayRotation
 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
 import com.android.systemui.biometrics.shared.model.SensorStrength
-import com.android.systemui.biometrics.ui.viewmodel.SideFpsOverlayViewModel
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
-import com.android.systemui.bouncer.ui.BouncerView
-import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryFingerprintAuthInteractor
-import com.android.systemui.display.data.repository.FakeDisplayRepository
-import com.android.systemui.keyguard.DismissCallbackRegistry
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
-import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
-import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
-import com.android.systemui.log.SideFpsLogger
-import com.android.systemui.log.logcatLogBuffer
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
+import com.android.systemui.display.data.repository.displayRepository
+import com.android.systemui.display.data.repository.displayStateRepository
+import com.android.systemui.keyguard.ui.viewmodel.sideFpsProgressBarViewModel
+import com.android.systemui.kosmos.testScope
 import com.android.systemui.res.R
-import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.statusbar.phone.dozeServiceHost
-import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.testKosmos
-import com.android.systemui.unfold.compat.ScreenSizeFoldProvider
-import com.android.systemui.user.domain.interactor.SelectedUserInteractor
-import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.whenever
-import com.android.systemui.util.time.FakeSystemClock
-import java.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
@@ -120,42 +82,14 @@
     private val kosmos = testKosmos()
 
     @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
-    @Mock private lateinit var activityTaskManager: ActivityTaskManager
     @Mock private lateinit var displayManager: DisplayManager
-    @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
     @Mock
     private lateinit var fingerprintInteractiveToAuthProvider: FingerprintInteractiveToAuthProvider
-    @Mock private lateinit var fpsUnlockTracker: FpsUnlockTracker
-    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
     @Mock private lateinit var layoutInflater: LayoutInflater
-    @Mock private lateinit var screenSizeFoldProvider: ScreenSizeFoldProvider
-    @Mock private lateinit var selectedUserInteractor: SelectedUserInteractor
     @Mock private lateinit var sideFpsView: View
-    @Mock private lateinit var windowManager: WindowManager
 
     private val contextDisplayInfo = DisplayInfo()
 
-    private val bouncerRepository = FakeKeyguardBouncerRepository()
-    private val biometricSettingsRepository = FakeBiometricSettingsRepository()
-    private val biometricStatusRepository = FakeBiometricStatusRepository()
-    private val deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
-    private val displayRepository = FakeDisplayRepository()
-    private val displayStateRepository = FakeDisplayStateRepository()
-    private val fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
-
-    private lateinit var underTest: SideFpsOverlayViewBinder
-
-    private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
-    private lateinit var biometricStatusInteractor: BiometricStatusInteractor
-    private lateinit var deviceEntrySideFpsOverlayInteractor: DeviceEntrySideFpsOverlayInteractor
-    private lateinit var displayStateInteractor: DisplayStateInteractorImpl
-    private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
-    private lateinit var sfpsSensorInteractor: SideFpsSensorInteractor
-
-    private lateinit var sideFpsProgressBarViewModel: SideFpsProgressBarViewModel
-
-    private lateinit var viewModel: SideFpsOverlayViewModel
-
     private var displayWidth: Int = 0
     private var displayHeight: Int = 0
     private var boundsWidth: Int = 0
@@ -164,9 +98,6 @@
     private lateinit var deviceConfig: DeviceConfig
     private lateinit var sensorLocation: SensorLocationInternal
 
-    private val testScope = TestScope(StandardTestDispatcher())
-    private val fakeExecutor = FakeExecutor(FakeSystemClock())
-
     enum class DeviceConfig {
         X_ALIGNED,
         Y_ALIGNED,
@@ -184,122 +115,13 @@
                 Display(mock(DisplayManagerGlobal::class.java), 1, contextDisplayInfo, resources)
             )
 
-        alternateBouncerInteractor =
-            AlternateBouncerInteractor(
-                mock(StatusBarStateController::class.java),
-                mock(KeyguardStateController::class.java),
-                bouncerRepository,
-                fingerprintPropertyRepository,
-                biometricSettingsRepository,
-                FakeSystemClock(),
-                keyguardUpdateMonitor,
-                { mock(DeviceEntryFingerprintAuthInteractor::class.java) },
-                { mock(KeyguardInteractor::class.java) },
-                { mock(KeyguardTransitionInteractor::class.java) },
-                testScope.backgroundScope,
-            )
-
-        biometricStatusInteractor =
-            BiometricStatusInteractorImpl(
-                activityTaskManager,
-                biometricStatusRepository,
-                fingerprintPropertyRepository
-            )
-
-        displayStateInteractor =
-            DisplayStateInteractorImpl(
-                testScope.backgroundScope,
-                mContext,
-                fakeExecutor,
-                displayStateRepository,
-                displayRepository,
-            )
-        displayStateInteractor.setScreenSizeFoldProvider(screenSizeFoldProvider)
-
-        primaryBouncerInteractor =
-            PrimaryBouncerInteractor(
-                bouncerRepository,
-                mock(BouncerView::class.java),
-                mock(Handler::class.java),
-                mock(KeyguardStateController::class.java),
-                mock(KeyguardSecurityModel::class.java),
-                mock(PrimaryBouncerCallbackInteractor::class.java),
-                mock(FalsingCollector::class.java),
-                mock(DismissCallbackRegistry::class.java),
-                mContext,
-                keyguardUpdateMonitor,
-                FakeTrustRepository(),
-                testScope.backgroundScope,
-                selectedUserInteractor,
-                faceAuthInteractor
-            )
-
-        deviceEntrySideFpsOverlayInteractor =
-            DeviceEntrySideFpsOverlayInteractor(
-                testScope.backgroundScope,
-                mContext,
-                deviceEntryFingerprintAuthRepository,
-                kosmos.sceneInteractor,
-                primaryBouncerInteractor,
-                alternateBouncerInteractor,
-                keyguardUpdateMonitor
-            )
+        kosmos.layoutInflater = layoutInflater
 
         whenever(fingerprintInteractiveToAuthProvider.enabledForCurrentUser)
             .thenReturn(MutableStateFlow(false))
 
-        sfpsSensorInteractor =
-            SideFpsSensorInteractor(
-                mContext,
-                fingerprintPropertyRepository,
-                windowManager,
-                displayStateInteractor,
-                Optional.of(fingerprintInteractiveToAuthProvider),
-                kosmos.biometricSettingsRepository,
-                kosmos.keyguardTransitionInteractor,
-                SideFpsLogger(logcatLogBuffer("SfpsLogger"))
-            )
-
-        sideFpsProgressBarViewModel =
-            SideFpsProgressBarViewModel(
-                mContext,
-                biometricStatusInteractor,
-                kosmos.deviceEntryFingerprintAuthInteractor,
-                sfpsSensorInteractor,
-                kosmos.dozeServiceHost,
-                kosmos.keyguardInteractor,
-                displayStateInteractor,
-                UnconfinedTestDispatcher(),
-                testScope.backgroundScope,
-                kosmos.powerInteractor,
-            )
-
-        viewModel =
-            SideFpsOverlayViewModel(
-                mContext,
-                biometricStatusInteractor,
-                deviceEntrySideFpsOverlayInteractor,
-                displayStateInteractor,
-                sfpsSensorInteractor,
-                sideFpsProgressBarViewModel
-            )
-
-        underTest =
-            SideFpsOverlayViewBinder(
-                testScope.backgroundScope,
-                mContext,
-                { biometricStatusInteractor },
-                { displayStateInteractor },
-                { deviceEntrySideFpsOverlayInteractor },
-                { fpsUnlockTracker },
-                { layoutInflater },
-                { sideFpsProgressBarViewModel },
-                { sfpsSensorInteractor },
-                { windowManager }
-            )
-
         context.addMockSystemService(DisplayManager::class.java, displayManager)
-        context.addMockSystemService(WindowManager::class.java, windowManager)
+        context.addMockSystemService(WindowManager::class.java, kosmos.windowManager)
 
         `when`(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sideFpsView)
         `when`(sideFpsView.requireViewById<LottieAnimationView>(eq(R.id.sidefps_animation)))
@@ -320,16 +142,16 @@
 
     @Test
     fun verifyIndicatorNotAdded_whenInRearDisplayMode() {
-        testScope.runTest {
+        kosmos.testScope.runTest {
             setupTestConfiguration(
                 DeviceConfig.X_ALIGNED,
                 rotation = DisplayRotation.ROTATION_0,
                 isInRearDisplayMode = true
             )
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.NotRunning
             )
-            sideFpsProgressBarViewModel.setVisible(false)
+            kosmos.sideFpsProgressBarViewModel.setVisible(false)
             updatePrimaryBouncer(
                 isShowing = true,
                 isAnimatingAway = false,
@@ -338,22 +160,22 @@
             )
             runCurrent()
 
-            verify(windowManager, never()).addView(any(), any())
+            verify(kosmos.windowManager, never()).addView(any(), any())
         }
     }
 
     @Test
     fun verifyIndicatorShowAndHide_onPrimaryBouncerShowAndHide() {
-        testScope.runTest {
+        kosmos.testScope.runTest {
             setupTestConfiguration(
                 DeviceConfig.X_ALIGNED,
                 rotation = DisplayRotation.ROTATION_0,
                 isInRearDisplayMode = false
             )
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.NotRunning
             )
-            sideFpsProgressBarViewModel.setVisible(false)
+            kosmos.sideFpsProgressBarViewModel.setVisible(false)
             // Show primary bouncer
             updatePrimaryBouncer(
                 isShowing = true,
@@ -363,7 +185,7 @@
             )
             runCurrent()
 
-            verify(windowManager).addView(any(), any())
+            verify(kosmos.windowManager).addView(any(), any())
 
             // Hide primary bouncer
             updatePrimaryBouncer(
@@ -374,45 +196,45 @@
             )
             runCurrent()
 
-            verify(windowManager).removeView(any())
+            verify(kosmos.windowManager).removeView(any())
         }
     }
 
     @Test
     fun verifyIndicatorShowAndHide_onAlternateBouncerShowAndHide() {
-        testScope.runTest {
+        kosmos.testScope.runTest {
             setupTestConfiguration(
                 DeviceConfig.X_ALIGNED,
                 rotation = DisplayRotation.ROTATION_0,
                 isInRearDisplayMode = false
             )
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.NotRunning
             )
-            sideFpsProgressBarViewModel.setVisible(false)
+            kosmos.sideFpsProgressBarViewModel.setVisible(false)
             // Show alternate bouncer
-            bouncerRepository.setAlternateVisible(true)
+            kosmos.keyguardBouncerRepository.setAlternateVisible(true)
             runCurrent()
 
-            verify(windowManager).addView(any(), any())
+            verify(kosmos.windowManager).addView(any(), any())
 
             // Hide alternate bouncer
-            bouncerRepository.setAlternateVisible(false)
+            kosmos.keyguardBouncerRepository.setAlternateVisible(false)
             runCurrent()
 
-            verify(windowManager).removeView(any())
+            verify(kosmos.windowManager).removeView(any())
         }
     }
 
     @Test
     fun verifyIndicatorShownAndHidden_onSystemServerAuthenticationStartedAndStopped() {
-        testScope.runTest {
+        kosmos.testScope.runTest {
             setupTestConfiguration(
                 DeviceConfig.X_ALIGNED,
                 rotation = DisplayRotation.ROTATION_0,
                 isInRearDisplayMode = false
             )
-            sideFpsProgressBarViewModel.setVisible(false)
+            kosmos.sideFpsProgressBarViewModel.setVisible(false)
             updatePrimaryBouncer(
                 isShowing = false,
                 isAnimatingAway = false,
@@ -420,20 +242,20 @@
                 isUnlockingWithFpAllowed = true
             )
             // System server authentication started
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.BiometricPromptAuthentication
             )
             runCurrent()
 
-            verify(windowManager).addView(any(), any())
+            verify(kosmos.windowManager).addView(any(), any())
 
             // System server authentication stopped
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.NotRunning
             )
             runCurrent()
 
-            verify(windowManager).removeView(any())
+            verify(kosmos.windowManager).removeView(any())
         }
     }
 
@@ -441,17 +263,17 @@
     // On progress bar hidden - show indicator
     @Test
     fun verifyIndicatorProgressBarInteraction() {
-        testScope.runTest {
+        kosmos.testScope.runTest {
             // Pre-auth conditions
             setupTestConfiguration(
                 DeviceConfig.X_ALIGNED,
                 rotation = DisplayRotation.ROTATION_0,
                 isInRearDisplayMode = false
             )
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.NotRunning
             )
-            sideFpsProgressBarViewModel.setVisible(false)
+            kosmos.sideFpsProgressBarViewModel.setVisible(false)
 
             // Show primary bouncer
             updatePrimaryBouncer(
@@ -462,26 +284,26 @@
             )
             runCurrent()
 
-            val inOrder = inOrder(windowManager)
+            val inOrder = inOrder(kosmos.windowManager)
 
             // Verify indicator shown
-            inOrder.verify(windowManager).addView(any(), any())
+            inOrder.verify(kosmos.windowManager).addView(any(), any())
 
             // Set progress bar visible
-            sideFpsProgressBarViewModel.setVisible(true)
+            kosmos.sideFpsProgressBarViewModel.setVisible(true)
 
             runCurrent()
 
             // Verify indicator hidden
-            inOrder.verify(windowManager).removeView(any())
+            inOrder.verify(kosmos.windowManager).removeView(any())
 
             // Set progress bar invisible
-            sideFpsProgressBarViewModel.setVisible(false)
+            kosmos.sideFpsProgressBarViewModel.setVisible(false)
 
             runCurrent()
 
             // Verify indicator shown
-            inOrder.verify(windowManager).addView(any(), any())
+            inOrder.verify(kosmos.windowManager).addView(any(), any())
         }
     }
 
@@ -491,14 +313,16 @@
         fpsDetectionRunning: Boolean,
         isUnlockingWithFpAllowed: Boolean,
     ) {
-        bouncerRepository.setPrimaryShow(isShowing)
-        bouncerRepository.setPrimaryStartingToHide(false)
+        kosmos.keyguardBouncerRepository.setPrimaryShow(isShowing)
+        kosmos.keyguardBouncerRepository.setPrimaryStartingToHide(false)
         val primaryStartDisappearAnimation = if (isAnimatingAway) Runnable {} else null
-        bouncerRepository.setPrimaryStartDisappearAnimation(primaryStartDisappearAnimation)
+        kosmos.keyguardBouncerRepository.setPrimaryStartDisappearAnimation(
+            primaryStartDisappearAnimation
+        )
 
-        whenever(keyguardUpdateMonitor.isFingerprintDetectionRunning)
+        whenever(kosmos.keyguardUpdateMonitor.isFingerprintDetectionRunning)
             .thenReturn(fpsDetectionRunning)
-        whenever(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
+        whenever(kosmos.keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
             .thenReturn(isUnlockingWithFpAllowed)
         mContext.orCreateTestableResources.addOverride(
             R.bool.config_show_sidefps_hint_on_bouncer,
@@ -530,7 +354,7 @@
             }
         }
 
-        whenever(windowManager.maximumWindowMetrics)
+        whenever(kosmos.windowManager.maximumWindowMetrics)
             .thenReturn(
                 WindowMetrics(
                     Rect(0, 0, displayWidth, displayHeight),
@@ -540,17 +364,17 @@
 
         contextDisplayInfo.uniqueId = DISPLAY_ID
 
-        fingerprintPropertyRepository.setProperties(
+        kosmos.fingerprintPropertyRepository.setProperties(
             sensorId = 1,
             strength = SensorStrength.STRONG,
             sensorType = FingerprintSensorType.POWER_BUTTON,
             sensorLocations = mapOf(DISPLAY_ID to sensorLocation)
         )
 
-        displayStateRepository.setIsInRearDisplayMode(isInRearDisplayMode)
-        displayStateRepository.setCurrentRotation(rotation)
-        displayRepository.emitDisplayChangeEvent(0)
-        underTest.start()
+        kosmos.displayStateRepository.setIsInRearDisplayMode(isInRearDisplayMode)
+        kosmos.displayStateRepository.setCurrentRotation(rotation)
+        kosmos.displayRepository.emitDisplayChangeEvent(0)
+        kosmos.sideFpsOverlayViewBinder.start()
         runCurrent()
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
index 05ec64e..b065393 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
@@ -22,74 +22,39 @@
 import android.graphics.Rect
 import android.hardware.biometrics.SensorLocationInternal
 import android.hardware.display.DisplayManagerGlobal
-import android.os.Handler
 import android.view.Display
 import android.view.DisplayInfo
 import android.view.WindowInsets
-import android.view.WindowManager
 import android.view.WindowMetrics
+import android.view.windowManager
 import androidx.test.filters.SmallTest
 import com.airbnb.lottie.model.KeyPath
-import com.android.keyguard.KeyguardSecurityModel
-import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.keyguardUpdateMonitor
 import com.android.settingslib.Utils
 import com.android.systemui.Flags.FLAG_CONSTRAINT_BP
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.biometrics.FingerprintInteractiveToAuthProvider
-import com.android.systemui.biometrics.data.repository.FakeBiometricStatusRepository
-import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
 import com.android.systemui.biometrics.data.repository.biometricStatusRepository
-import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
-import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
-import com.android.systemui.biometrics.domain.interactor.biometricStatusInteractor
+import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
+import com.android.systemui.biometrics.domain.interactor.displayStateInteractor
 import com.android.systemui.biometrics.shared.model.AuthenticationReason
 import com.android.systemui.biometrics.shared.model.DisplayRotation
 import com.android.systemui.biometrics.shared.model.FingerprintSensorType
 import com.android.systemui.biometrics.shared.model.LottieCallback
 import com.android.systemui.biometrics.shared.model.SensorStrength
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
-import com.android.systemui.bouncer.ui.BouncerView
-import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryFingerprintAuthInteractor
-import com.android.systemui.display.data.repository.FakeDisplayRepository
-import com.android.systemui.keyguard.DismissCallbackRegistry
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.data.repository.FakeTrustRepository
-import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
-import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
-import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
-import com.android.systemui.kosmos.testDispatcher
-import com.android.systemui.log.SideFpsLogger
-import com.android.systemui.log.logcatLogBuffer
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.display.data.repository.displayRepository
+import com.android.systemui.display.data.repository.displayStateRepository
+import com.android.systemui.keyguard.ui.viewmodel.sideFpsProgressBarViewModel
+import com.android.systemui.kosmos.testScope
 import com.android.systemui.res.R
-import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.statusbar.phone.dozeServiceHost
-import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.testKosmos
 import com.android.systemui.unfold.compat.ScreenSizeFoldProvider
-import com.android.systemui.user.domain.interactor.SelectedUserInteractor
-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.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
@@ -111,24 +76,12 @@
     private val kosmos = testKosmos()
     @JvmField @Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
 
-    @Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
     @Mock
     private lateinit var fingerprintInteractiveToAuthProvider: FingerprintInteractiveToAuthProvider
-    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
     @Mock private lateinit var screenSizeFoldProvider: ScreenSizeFoldProvider
-    @Mock private lateinit var selectedUserInteractor: SelectedUserInteractor
-    @Mock private lateinit var windowManager: WindowManager
 
     private val contextDisplayInfo = DisplayInfo()
 
-    private val bouncerRepository = FakeKeyguardBouncerRepository()
-    private val biometricSettingsRepository = FakeBiometricSettingsRepository()
-    private val biometricStatusRepository = FakeBiometricStatusRepository()
-    private val deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
-    private val displayRepository = FakeDisplayRepository()
-    private val displayStateRepository = FakeDisplayStateRepository()
-    private val fingerprintPropertyRepository = FakeFingerprintPropertyRepository()
-
     private val indicatorColor =
         Utils.getColorAttrDefaultColor(
             context,
@@ -147,16 +100,6 @@
     private val color_blue400 =
         context.getColor(com.android.settingslib.color.R.color.settingslib_color_blue400)
 
-    private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
-    private lateinit var deviceEntrySideFpsOverlayInteractor: DeviceEntrySideFpsOverlayInteractor
-    private lateinit var displayStateInteractor: DisplayStateInteractorImpl
-    private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
-    private lateinit var sfpsSensorInteractor: SideFpsSensorInteractor
-
-    private lateinit var sideFpsProgressBarViewModel: SideFpsProgressBarViewModel
-
-    private lateinit var underTest: SideFpsOverlayViewModel
-
     private var displayWidth: Int = 0
     private var displayHeight: Int = 0
     private var boundsWidth: Int = 0
@@ -165,9 +108,6 @@
     private lateinit var deviceConfig: DeviceConfig
     private lateinit var sensorLocation: SensorLocationInternal
 
-    private val testScope = TestScope(StandardTestDispatcher())
-    private val fakeExecutor = FakeExecutor(FakeSystemClock())
-
     enum class DeviceConfig {
         X_ALIGNED,
         Y_ALIGNED,
@@ -182,129 +122,40 @@
             .thenReturn(
                 Display(mock(DisplayManagerGlobal::class.java), 1, contextDisplayInfo, resources)
             )
-        kosmos.biometricStatusRepository = biometricStatusRepository
-
-        alternateBouncerInteractor =
-            AlternateBouncerInteractor(
-                mock(StatusBarStateController::class.java),
-                mock(KeyguardStateController::class.java),
-                bouncerRepository,
-                fingerprintPropertyRepository,
-                biometricSettingsRepository,
-                FakeSystemClock(),
-                keyguardUpdateMonitor,
-                { mock(DeviceEntryFingerprintAuthInteractor::class.java) },
-                { mock(KeyguardInteractor::class.java) },
-                { mock(KeyguardTransitionInteractor::class.java) },
-                testScope.backgroundScope,
-            )
-
-        displayStateInteractor =
-            DisplayStateInteractorImpl(
-                testScope.backgroundScope,
-                mContext,
-                fakeExecutor,
-                displayStateRepository,
-                displayRepository,
-            )
-        displayStateInteractor.setScreenSizeFoldProvider(screenSizeFoldProvider)
-
-        primaryBouncerInteractor =
-            PrimaryBouncerInteractor(
-                bouncerRepository,
-                mock(BouncerView::class.java),
-                mock(Handler::class.java),
-                mock(KeyguardStateController::class.java),
-                mock(KeyguardSecurityModel::class.java),
-                mock(PrimaryBouncerCallbackInteractor::class.java),
-                mock(FalsingCollector::class.java),
-                mock(DismissCallbackRegistry::class.java),
-                mContext,
-                keyguardUpdateMonitor,
-                FakeTrustRepository(),
-                testScope.backgroundScope,
-                selectedUserInteractor,
-                faceAuthInteractor
-            )
-
-        deviceEntrySideFpsOverlayInteractor =
-            DeviceEntrySideFpsOverlayInteractor(
-                testScope.backgroundScope,
-                mContext,
-                deviceEntryFingerprintAuthRepository,
-                kosmos.sceneInteractor,
-                primaryBouncerInteractor,
-                alternateBouncerInteractor,
-                keyguardUpdateMonitor
-            )
+        kosmos.displayStateInteractor.setScreenSizeFoldProvider(screenSizeFoldProvider)
 
         whenever(fingerprintInteractiveToAuthProvider.enabledForCurrentUser)
             .thenReturn(MutableStateFlow(false))
-
-        sfpsSensorInteractor =
-            SideFpsSensorInteractor(
-                mContext,
-                fingerprintPropertyRepository,
-                windowManager,
-                displayStateInteractor,
-                Optional.of(fingerprintInteractiveToAuthProvider),
-                kosmos.biometricSettingsRepository,
-                kosmos.keyguardTransitionInteractor,
-                SideFpsLogger(logcatLogBuffer("SfpsLogger"))
-            )
-
-        sideFpsProgressBarViewModel =
-            SideFpsProgressBarViewModel(
-                mContext,
-                kosmos.biometricStatusInteractor,
-                kosmos.deviceEntryFingerprintAuthInteractor,
-                sfpsSensorInteractor,
-                kosmos.dozeServiceHost,
-                kosmos.keyguardInteractor,
-                displayStateInteractor,
-                kosmos.testDispatcher,
-                testScope.backgroundScope,
-                kosmos.powerInteractor
-            )
-
-        underTest =
-            SideFpsOverlayViewModel(
-                mContext,
-                kosmos.biometricStatusInteractor,
-                deviceEntrySideFpsOverlayInteractor,
-                displayStateInteractor,
-                sfpsSensorInteractor,
-                sideFpsProgressBarViewModel,
-            )
     }
 
     @Test
     fun updatesOverlayViewProperties_onDisplayRotationChange_xAlignedSensor() {
-        testScope.runTest {
+        kosmos.testScope.runTest {
             setupTestConfiguration(
                 DeviceConfig.X_ALIGNED,
                 rotation = DisplayRotation.ROTATION_0,
                 isInRearDisplayMode = false
             )
 
-            val overlayViewProperties by collectLastValue(underTest.overlayViewProperties)
+            val overlayViewProperties by
+                collectLastValue(kosmos.sideFpsOverlayViewModel.overlayViewProperties)
 
             runCurrent()
 
             assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse_landscape)
             assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(0f)
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
 
             assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse)
             assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(180f)
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
 
             assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse_landscape)
             assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(180f)
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
 
             assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse)
             assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(0f)
@@ -313,31 +164,32 @@
 
     @Test
     fun updatesOverlayViewProperties_onDisplayRotationChange_yAlignedSensor() {
-        testScope.runTest {
+        kosmos.testScope.runTest {
             setupTestConfiguration(
                 DeviceConfig.Y_ALIGNED,
                 rotation = DisplayRotation.ROTATION_0,
                 isInRearDisplayMode = false
             )
 
-            val overlayViewProperties by collectLastValue(underTest.overlayViewProperties)
+            val overlayViewProperties by
+                collectLastValue(kosmos.sideFpsOverlayViewModel.overlayViewProperties)
 
             runCurrent()
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_0)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_0)
             assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse)
             assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(0f)
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
 
             assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse_landscape)
             assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(0f)
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
             assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse)
             assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(180f)
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
 
             assertThat(overlayViewProperties?.indicatorAsset).isEqualTo(R.raw.sfps_pulse_landscape)
             assertThat(overlayViewProperties?.overlayViewRotation).isEqualTo(180f)
@@ -346,7 +198,7 @@
 
     @Test
     fun updatesOverlayViewParams_onDisplayRotationChange_xAlignedSensor() {
-        testScope.runTest {
+        kosmos.testScope.runTest {
             mSetFlagsRule.disableFlags(FLAG_CONSTRAINT_BP)
             setupTestConfiguration(
                 DeviceConfig.X_ALIGNED,
@@ -354,16 +206,17 @@
                 isInRearDisplayMode = false
             )
 
-            val overlayViewParams by collectLastValue(underTest.overlayViewParams)
+            val overlayViewParams by
+                collectLastValue(kosmos.sideFpsOverlayViewModel.overlayViewParams)
 
-            underTest.setLottieBounds(Rect(0, 0, boundsWidth, boundsHeight))
+            kosmos.sideFpsOverlayViewModel.setLottieBounds(Rect(0, 0, boundsWidth, boundsHeight))
             runCurrent()
 
             assertThat(overlayViewParams).isNotNull()
             assertThat(overlayViewParams!!.x).isEqualTo(sensorLocation.sensorLocationX)
             assertThat(overlayViewParams!!.y).isEqualTo(0)
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
             assertThat(overlayViewParams).isNotNull()
             assertThat(overlayViewParams!!.x).isEqualTo(0)
             assertThat(overlayViewParams!!.y)
@@ -371,7 +224,7 @@
                     displayHeight - sensorLocation.sensorLocationX - sensorLocation.sensorRadius * 2
                 )
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
             assertThat(overlayViewParams).isNotNull()
             assertThat(overlayViewParams!!.x)
                 .isEqualTo(
@@ -379,7 +232,7 @@
                 )
             assertThat(overlayViewParams!!.y).isEqualTo(displayHeight - boundsHeight)
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
             assertThat(overlayViewParams).isNotNull()
             assertThat(overlayViewParams!!.x).isEqualTo(displayWidth - boundsWidth)
             assertThat(overlayViewParams!!.y).isEqualTo(sensorLocation.sensorLocationX)
@@ -388,7 +241,7 @@
 
     @Test
     fun updatesOverlayViewParams_onDisplayRotationChange_yAlignedSensor() {
-        testScope.runTest {
+        kosmos.testScope.runTest {
             mSetFlagsRule.disableFlags(FLAG_CONSTRAINT_BP)
             setupTestConfiguration(
                 DeviceConfig.Y_ALIGNED,
@@ -396,21 +249,22 @@
                 isInRearDisplayMode = false
             )
 
-            val overlayViewParams by collectLastValue(underTest.overlayViewParams)
+            val overlayViewParams by
+                collectLastValue(kosmos.sideFpsOverlayViewModel.overlayViewParams)
 
-            underTest.setLottieBounds(Rect(0, 0, boundsWidth, boundsHeight))
+            kosmos.sideFpsOverlayViewModel.setLottieBounds(Rect(0, 0, boundsWidth, boundsHeight))
             runCurrent()
 
             assertThat(overlayViewParams).isNotNull()
             assertThat(overlayViewParams!!.x).isEqualTo(displayWidth - boundsWidth)
             assertThat(overlayViewParams!!.y).isEqualTo(sensorLocation.sensorLocationY)
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_90)
             assertThat(overlayViewParams).isNotNull()
             assertThat(overlayViewParams!!.x).isEqualTo(sensorLocation.sensorLocationY)
             assertThat(overlayViewParams!!.y).isEqualTo(0)
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_180)
             assertThat(overlayViewParams).isNotNull()
             assertThat(overlayViewParams!!.x).isEqualTo(0)
             assertThat(overlayViewParams!!.y)
@@ -418,7 +272,7 @@
                     displayHeight - sensorLocation.sensorLocationY - sensorLocation.sensorRadius * 2
                 )
 
-            displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
+            kosmos.displayStateRepository.setCurrentRotation(DisplayRotation.ROTATION_270)
             assertThat(overlayViewParams).isNotNull()
             assertThat(overlayViewParams!!.x)
                 .isEqualTo(
@@ -430,13 +284,13 @@
 
     @Test
     fun updatesLottieCallbacks_onShowIndicatorForDeviceEntry() {
-        testScope.runTest {
-            val lottieCallbacks by collectLastValue(underTest.lottieCallbacks)
+        kosmos.testScope.runTest {
+            val lottieCallbacks by collectLastValue(kosmos.sideFpsOverlayViewModel.lottieCallbacks)
 
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.NotRunning
             )
-            sideFpsProgressBarViewModel.setVisible(false)
+            kosmos.sideFpsProgressBarViewModel.setVisible(false)
 
             updatePrimaryBouncer(
                 isShowing = true,
@@ -457,14 +311,14 @@
 
     @Test
     fun updatesLottieCallbacks_onShowIndicatorForSystemServer_inDarkMode() {
-        testScope.runTest {
-            val lottieCallbacks by collectLastValue(underTest.lottieCallbacks)
+        kosmos.testScope.runTest {
+            val lottieCallbacks by collectLastValue(kosmos.sideFpsOverlayViewModel.lottieCallbacks)
             setDarkMode(true)
 
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.BiometricPromptAuthentication
             )
-            sideFpsProgressBarViewModel.setVisible(false)
+            kosmos.sideFpsProgressBarViewModel.setVisible(false)
 
             updatePrimaryBouncer(
                 isShowing = false,
@@ -483,14 +337,14 @@
 
     @Test
     fun updatesLottieCallbacks_onShowIndicatorForSystemServer_inLightMode() {
-        testScope.runTest {
-            val lottieCallbacks by collectLastValue(underTest.lottieCallbacks)
+        kosmos.testScope.runTest {
+            val lottieCallbacks by collectLastValue(kosmos.sideFpsOverlayViewModel.lottieCallbacks)
             setDarkMode(false)
 
-            biometricStatusRepository.setFingerprintAuthenticationReason(
+            kosmos.biometricStatusRepository.setFingerprintAuthenticationReason(
                 AuthenticationReason.BiometricPromptAuthentication
             )
-            sideFpsProgressBarViewModel.setVisible(false)
+            kosmos.sideFpsProgressBarViewModel.setVisible(false)
 
             updatePrimaryBouncer(
                 isShowing = false,
@@ -526,14 +380,16 @@
         fpsDetectionRunning: Boolean,
         isUnlockingWithFpAllowed: Boolean,
     ) {
-        bouncerRepository.setPrimaryShow(isShowing)
-        bouncerRepository.setPrimaryStartingToHide(false)
+        kosmos.keyguardBouncerRepository.setPrimaryShow(isShowing)
+        kosmos.keyguardBouncerRepository.setPrimaryStartingToHide(false)
         val primaryStartDisappearAnimation = if (isAnimatingAway) Runnable {} else null
-        bouncerRepository.setPrimaryStartDisappearAnimation(primaryStartDisappearAnimation)
+        kosmos.keyguardBouncerRepository.setPrimaryStartDisappearAnimation(
+            primaryStartDisappearAnimation
+        )
 
-        whenever(keyguardUpdateMonitor.isFingerprintDetectionRunning)
+        whenever(kosmos.keyguardUpdateMonitor.isFingerprintDetectionRunning)
             .thenReturn(fpsDetectionRunning)
-        whenever(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
+        whenever(kosmos.keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
             .thenReturn(isUnlockingWithFpAllowed)
         mContext.orCreateTestableResources.addOverride(
             R.bool.config_show_sidefps_hint_on_bouncer,
@@ -565,7 +421,7 @@
             }
         }
 
-        whenever(windowManager.maximumWindowMetrics)
+        whenever(kosmos.windowManager.maximumWindowMetrics)
             .thenReturn(
                 WindowMetrics(
                     Rect(0, 0, displayWidth, displayHeight),
@@ -575,18 +431,17 @@
 
         contextDisplayInfo.uniqueId = DISPLAY_ID
 
-        fingerprintPropertyRepository.setProperties(
+        kosmos.fingerprintPropertyRepository.setProperties(
             sensorId = 1,
             strength = SensorStrength.STRONG,
             sensorType = FingerprintSensorType.POWER_BUTTON,
             sensorLocations = mapOf(DISPLAY_ID to sensorLocation)
         )
 
-        displayStateRepository.setIsInRearDisplayMode(isInRearDisplayMode)
+        kosmos.displayStateRepository.setIsInRearDisplayMode(isInRearDisplayMode)
+        kosmos.displayStateRepository.setCurrentRotation(rotation)
 
-        displayStateRepository.setCurrentRotation(rotation)
-
-        displayRepository.emitDisplayChangeEvent(0)
+        kosmos.displayRepository.emitDisplayChangeEvent(0)
         runCurrent()
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
index 8e5ddc7..bc6c459 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java
@@ -50,6 +50,8 @@
 import com.android.systemui.util.sensors.ThresholdSensor;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import kotlinx.coroutines.flow.StateFlowKt;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -58,8 +60,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import kotlinx.coroutines.flow.StateFlowKt;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java
index db85522..63e43d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayUtilsTest.java
@@ -39,8 +39,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import com.google.android.collect.Lists;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/IntentCreatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/IntentCreatorTest.java
index fb07e6e..ea6cb3b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/IntentCreatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/IntentCreatorTest.java
@@ -28,8 +28,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt
index 9e007e9..63b4ff7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/common/ui/domain/interactor/ConfigurationInteractorTest.kt
@@ -91,7 +91,7 @@
     @Test
     fun maxBoundsChange_emitsMaxBoundsChange() =
         testScope.runTest {
-            val values by collectValues(underTest.naturalMaxBounds)
+            val values by collectValues(underTest.maxBounds)
 
             updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
             runCurrent()
@@ -109,7 +109,7 @@
     @Test
     fun maxBoundsSameOnConfigChange_doesNotEmitMaxBoundsChange() =
         testScope.runTest {
-            val values by collectValues(underTest.naturalMaxBounds)
+            val values by collectValues(underTest.maxBounds)
 
             updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
             runCurrent()
@@ -122,6 +122,48 @@
     @Test
     fun firstMaxBoundsChange_emitsMaxBoundsChange() =
         testScope.runTest {
+            val values by collectValues(underTest.maxBounds)
+
+            updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
+            runCurrent()
+
+            assertThat(values).containsExactly(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT))
+        }
+
+    @Test
+    fun maxBoundsChange_emitsNaturalMaxBoundsChange() =
+        testScope.runTest {
+            val values by collectValues(underTest.naturalMaxBounds)
+
+            updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
+            runCurrent()
+            updateDisplay(width = DISPLAY_WIDTH * 2, height = DISPLAY_HEIGHT * 3)
+            runCurrent()
+
+            assertThat(values)
+                .containsExactly(
+                    Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
+                    Rect(0, 0, DISPLAY_WIDTH * 2, DISPLAY_HEIGHT * 3),
+                )
+                .inOrder()
+        }
+
+    @Test
+    fun maxBoundsSameOnConfigChange_doesNotEmitNaturalMaxBoundsChange() =
+        testScope.runTest {
+            val values by collectValues(underTest.naturalMaxBounds)
+
+            updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
+            runCurrent()
+            updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
+            runCurrent()
+
+            assertThat(values).containsExactly(Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT))
+        }
+
+    @Test
+    fun firstMaxBoundsChange_emitsNaturalMaxBoundsChange() =
+        testScope.runTest {
             val values by collectValues(underTest.naturalMaxBounds)
 
             updateDisplay(width = DISPLAY_WIDTH, height = DISPLAY_HEIGHT)
@@ -131,7 +173,7 @@
         }
 
     @Test
-    fun displayRotatedButMaxBoundsTheSame_doesNotEmitNewMaxBoundsChange() =
+    fun displayRotatedButMaxBoundsTheSame_doesNotEmitNewNaturalMaxBoundsChange() =
         testScope.runTest {
             val values by collectValues(underTest.naturalMaxBounds)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
index 98f7f59..4c4205e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsViewTest.java
@@ -33,9 +33,9 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.common.ui.view.SeekBarWithIconButtonsView.OnSeekBarWithIconButtonsChangeListener;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationLayoutEngineTest.java b/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationLayoutEngineTest.java
index a78f0b7..baaeee1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationLayoutEngineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationLayoutEngineTest.java
@@ -28,9 +28,9 @@
 import androidx.constraintlayout.widget.ConstraintLayout;
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.complication.ComplicationLayoutEngine.Margins;
+import com.android.systemui.res.R;
 import com.android.systemui.touch.TouchInsetManager;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationUtilsTest.java
index 235c56b..e23e1f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/complication/ComplicationUtilsTest.java
@@ -27,7 +27,6 @@
 import static com.android.systemui.complication.ComplicationUtils.convertComplicationType;
 import static com.android.systemui.complication.ComplicationUtils.convertComplicationTypes;
 
-
 import static com.google.common.truth.Truth.assertThat;
 
 import android.testing.AndroidTestingRunner;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt
index 5581f0c..431fef6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/BiometricMessageInteractorTest.kt
@@ -17,7 +17,9 @@
 package com.android.systemui.deviceentry.domain.interactor
 
 import android.content.res.mainResources
-import android.hardware.face.FaceManager
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_RIGHT
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE
+import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT
 import android.hardware.fingerprint.FingerprintManager
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
@@ -266,7 +268,7 @@
             faceAuthRepository.setAuthenticationStatus(
                 HelpFaceAuthenticationStatus(
                     msg = "Move left",
-                    msgId = FaceManager.FACE_ACQUIRED_TOO_RIGHT,
+                    msgId = FACE_ACQUIRED_TOO_RIGHT,
                 )
             )
 
@@ -293,7 +295,7 @@
             faceAuthRepository.setAuthenticationStatus(
                 HelpFaceAuthenticationStatus(
                     msg = "Move left",
-                    msgId = FaceManager.FACE_ACQUIRED_TOO_RIGHT,
+                    msgId = FACE_ACQUIRED_TOO_RIGHT,
                 )
             )
 
@@ -318,7 +320,7 @@
             faceAuthRepository.setAuthenticationStatus(
                 HelpFaceAuthenticationStatus(
                     msg = "Move left",
-                    msgId = FaceManager.FACE_ACQUIRED_TOO_RIGHT,
+                    msgId = FACE_ACQUIRED_TOO_RIGHT,
                 )
             )
 
@@ -333,10 +335,7 @@
 
             // WHEN authentication status error is FACE_ERROR_HW_UNAVAILABLE
             faceAuthRepository.setAuthenticationStatus(
-                ErrorFaceAuthenticationStatus(
-                    msgId = FaceManager.FACE_ERROR_HW_UNAVAILABLE,
-                    msg = "test"
-                )
+                ErrorFaceAuthenticationStatus(msgId = FACE_ERROR_HW_UNAVAILABLE, msg = "test")
             )
 
             // THEN faceErrorMessage isn't updated - it's still null since it was suppressed
@@ -350,10 +349,7 @@
 
             // WHEN authentication status error is FACE_ERROR_HW_UNAVAILABLE
             faceAuthRepository.setAuthenticationStatus(
-                ErrorFaceAuthenticationStatus(
-                    msgId = FaceManager.FACE_ERROR_HW_UNAVAILABLE,
-                    msg = "test"
-                )
+                ErrorFaceAuthenticationStatus(msgId = FACE_ERROR_HW_UNAVAILABLE, msg = "test")
             )
 
             // GIVEN face is allowed
@@ -370,7 +366,7 @@
 
             // WHEN authentication status error is FACE_ERROR_TIMEOUT
             faceAuthRepository.setAuthenticationStatus(
-                ErrorFaceAuthenticationStatus(msgId = FaceManager.FACE_ERROR_TIMEOUT, msg = "test")
+                ErrorFaceAuthenticationStatus(msgId = FACE_ERROR_TIMEOUT, msg = "test")
             )
 
             // GIVEN face is allowed
@@ -389,7 +385,7 @@
 
             // WHEN authentication status error is FACE_ERROR_TIMEOUT
             faceAuthRepository.setAuthenticationStatus(
-                ErrorFaceAuthenticationStatus(msgId = FaceManager.FACE_ERROR_TIMEOUT, msg = "test")
+                ErrorFaceAuthenticationStatus(msgId = FACE_ERROR_TIMEOUT, msg = "test")
             )
 
             // GIVEN face is allowed
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java
index ea7467f..e1dc696 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/AlwaysOnDisplayPolicyTest.java
@@ -24,8 +24,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java
index 9064470..92941f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuppressorTest.java
@@ -47,6 +47,8 @@
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
 
+import dagger.Lazy;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -57,8 +59,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import dagger.Lazy;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @UiThreadTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsColumnLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsColumnLayoutTest.java
index f89a0b6..f4fadaa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsColumnLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsColumnLayoutTest.java
@@ -30,8 +30,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.util.leak.RotationUtils;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java
index 5a97b74..84b1c00 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java
@@ -28,8 +28,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.util.leak.RotationUtils;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java
index a003e07..4c65b90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java
@@ -25,8 +25,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java
index 2d3ca60..28c01ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/ShutdownUiTest.java
@@ -40,7 +40,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class ShutdownUiTest extends SysuiTestCase {
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 709f779..59f7d61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -133,6 +133,10 @@
 import com.android.systemui.wallpapers.data.repository.FakeWallpaperRepository;
 import com.android.wm.shell.keyguard.KeyguardTransitions;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+import kotlinx.coroutines.flow.Flow;
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -143,10 +147,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import kotlinx.coroutines.CoroutineDispatcher;
-import kotlinx.coroutines.flow.Flow;
-import kotlinx.coroutines.test.TestScope;
-
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 @SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/logcat/LogAccessDialogActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/logcat/LogAccessDialogActivityTest.java
index eed7ecd..aef05a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/logcat/LogAccessDialogActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/logcat/LogAccessDialogActivityTest.java
@@ -31,8 +31,8 @@
 import androidx.test.platform.app.InstrumentationRegistry;
 
 import com.android.internal.app.ILogAccessDialogCallback;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
index b3cfcf2..857af66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataFilterImplTest.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.media.controls.MediaTestUtils
 import com.android.systemui.media.controls.data.repository.MediaFilterRepository
+import com.android.systemui.media.controls.data.repository.mediaFilterRepository
 import com.android.systemui.media.controls.shared.model.EXTRA_KEY_TRIGGER_RESUME
 import com.android.systemui.media.controls.shared.model.MediaCommonModel
 import com.android.systemui.media.controls.shared.model.MediaData
@@ -38,6 +39,7 @@
 import com.android.systemui.media.controls.util.MediaUiEventLogger
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.NotificationLockscreenUserManager
+import com.android.systemui.testKosmos
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.mockito.whenever
@@ -77,6 +79,7 @@
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper
 class MediaDataFilterImplTest : SysuiTestCase() {
+    val kosmos = testKosmos()
 
     @Mock private lateinit var listener: MediaDataProcessor.Listener
     @Mock private lateinit var userTracker: UserTracker
@@ -91,12 +94,12 @@
     @Mock private lateinit var cardAction: SmartspaceAction
 
     private lateinit var mediaDataFilter: MediaDataFilterImpl
-    private lateinit var repository: MediaFilterRepository
     private lateinit var testScope: TestScope
     private lateinit var dataMain: MediaData
     private lateinit var dataGuest: MediaData
     private lateinit var dataPrivateProfile: MediaData
     private val clock = FakeSystemClock()
+    private val repository: MediaFilterRepository = kosmos.mediaFilterRepository
 
     @Before
     fun setup() {
@@ -104,7 +107,6 @@
         MediaPlayerData.clear()
         whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false)
         testScope = TestScope()
-        repository = MediaFilterRepository(FakeSystemClock())
         mediaDataFilter =
             MediaDataFilterImpl(
                 context,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index ffb50c1..1de7ee3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -54,6 +54,7 @@
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.media.controls.data.repository.MediaDataRepository
 import com.android.systemui.media.controls.data.repository.MediaFilterRepository
+import com.android.systemui.media.controls.data.repository.mediaFilterRepository
 import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
 import com.android.systemui.media.controls.domain.resume.MediaResumeListener
 import com.android.systemui.media.controls.domain.resume.ResumeMediaBrowser
@@ -68,6 +69,7 @@
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.res.R
 import com.android.systemui.statusbar.SbnBuilder
+import com.android.systemui.testKosmos
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.capture
@@ -125,6 +127,7 @@
 @RunWithLooper(setAsMainLooper = true)
 @RunWith(AndroidTestingRunner::class)
 class MediaDataProcessorTest : SysuiTestCase() {
+    val kosmos = testKosmos()
 
     @JvmField @Rule val mockito = MockitoJUnit.rule()
     @Mock lateinit var mediaControllerFactory: MediaControllerFactory
@@ -168,7 +171,6 @@
     @Mock private lateinit var ugm: IUriGrantsManager
     @Mock private lateinit var imageSource: ImageDecoder.Source
     private lateinit var mediaDataRepository: MediaDataRepository
-    private lateinit var mediaFilterRepository: MediaFilterRepository
     private lateinit var testScope: TestScope
     private lateinit var testDispatcher: TestDispatcher
     private lateinit var testableLooper: TestableLooper
@@ -183,6 +185,7 @@
             Settings.Secure.MEDIA_CONTROLS_RECOMMENDATION,
             1
         )
+    private val mediaFilterRepository: MediaFilterRepository = kosmos.mediaFilterRepository
 
     private lateinit var staticMockSession: MockitoSession
 
@@ -210,7 +213,6 @@
         )
         testDispatcher = UnconfinedTestDispatcher()
         testScope = TestScope(testDispatcher)
-        mediaFilterRepository = MediaFilterRepository(clock)
         mediaDataRepository = MediaDataRepository(mediaFlags, dumpManager)
         mediaDataProcessor =
             MediaDataProcessor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
index c3daf84..0a5aace 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
@@ -36,6 +36,7 @@
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
 import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.media.controls.MediaTestUtils
 import com.android.systemui.media.controls.domain.pipeline.EMPTY_SMARTSPACE_MEDIA_DATA
@@ -44,6 +45,7 @@
 import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QS
 import com.android.systemui.media.controls.ui.view.MediaHostState
 import com.android.systemui.media.controls.ui.view.MediaScrollView
+import com.android.systemui.media.controls.ui.viewmodel.mediaCarouselViewModel
 import com.android.systemui.media.controls.util.MediaFlags
 import com.android.systemui.media.controls.util.MediaUiEventLogger
 import com.android.systemui.plugins.ActivityStarter
@@ -100,6 +102,7 @@
     val kosmos = testKosmos()
 
     @Mock lateinit var mediaControlPanelFactory: Provider<MediaControlPanel>
+    @Mock lateinit var mediaViewControllerFactory: Provider<MediaViewController>
     @Mock lateinit var panel: MediaControlPanel
     @Mock lateinit var visualStabilityProvider: VisualStabilityProvider
     @Mock lateinit var mediaHostStatesManager: MediaHostStatesManager
@@ -148,6 +151,7 @@
                 mediaHostStatesManager,
                 activityStarter,
                 clock,
+                kosmos.testDispatcher,
                 executor,
                 bgExecutor,
                 testDispatcher,
@@ -162,6 +166,8 @@
                 kosmos.keyguardTransitionInteractor,
                 globalSettings,
                 secureSettings,
+                kosmos.mediaCarouselViewModel,
+                mediaViewControllerFactory,
             )
         verify(configurationController).addCallback(capture(configListener))
         verify(mediaDataManager).addListener(capture(listener))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt
index cb4ab64..e1c2d3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModelTest.kt
@@ -29,12 +29,7 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.classifier.Classifier
-import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.kosmos.testDispatcher
-import com.android.systemui.media.controls.util.MediaFlags
-import com.android.systemui.media.controls.util.mediaFlags
 import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.testKosmos
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.concurrency.FakeRepeatableExecutor
 import com.android.systemui.util.time.FakeSystemClock
@@ -61,7 +56,6 @@
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 public class SeekBarViewModelTest : SysuiTestCase() {
-    val kosmos = testKosmos()
 
     private lateinit var viewModel: SeekBarViewModel
     private lateinit var fakeExecutor: FakeExecutor
@@ -81,7 +75,6 @@
     @Mock private lateinit var mockTransport: MediaController.TransportControls
     @Mock private lateinit var falsingManager: FalsingManager
     @Mock private lateinit var mockBar: SeekBar
-    @Mock private lateinit var mediaFlags: MediaFlags
     private val token1 = MediaSession.Token(1, null)
     private val token2 = MediaSession.Token(2, null)
 
@@ -90,18 +83,10 @@
     @Before
     fun setUp() {
         fakeExecutor = FakeExecutor(FakeSystemClock())
-        viewModel =
-            SeekBarViewModel(
-                kosmos.applicationCoroutineScope,
-                kosmos.testDispatcher,
-                FakeRepeatableExecutor(fakeExecutor),
-                falsingManager,
-                mediaFlags,
-            )
+        viewModel = SeekBarViewModel(FakeRepeatableExecutor(fakeExecutor), falsingManager)
         viewModel.logSeek = {}
         whenever(mockController.sessionToken).thenReturn(token1)
         whenever(mockBar.context).thenReturn(context)
-        whenever(mediaFlags.isMediaControlsRefactorEnabled()).thenReturn(false)
 
         // LiveData to run synchronously
         ArchTaskExecutor.getInstance().setDelegate(taskExecutor)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 2f057a2..95e34a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -46,8 +46,8 @@
 
 import com.android.settingslib.media.LocalMediaManager;
 import com.android.settingslib.media.MediaDevice;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import com.google.common.collect.ImmutableList;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
index 33a30e0..293f66b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/systemsounds/HomeSoundEffectControllerTest.java
@@ -45,7 +45,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class HomeSoundEffectControllerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
index 30d66dc..84a8ab0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -58,10 +58,10 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.appwidget.IAppWidgetService;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
 import com.android.systemui.people.widget.PeopleTileKey;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
index d0e8cce..3d1da00 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
@@ -60,9 +60,9 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.people.widget.PeopleTileKey;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java
index ff60fcd..f573358 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java
@@ -31,14 +31,14 @@
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import kotlinx.coroutines.CoroutineScope;
-
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 @SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
index 98e803f..5ae0c24 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterViewControllerTest.java
@@ -34,9 +34,9 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.res.R;
 import com.android.systemui.retail.data.repository.FakeRetailModeRepository;
 import com.android.systemui.retail.domain.interactor.RetailModeInteractorImpl;
 import com.android.systemui.settings.UserTracker;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index d3cd26b..df0ab34 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -50,10 +50,10 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.InstanceId;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.QSHost;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index 248af1e..b62d59d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -47,7 +47,7 @@
 import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.concurrency.FakeExecutor;
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 efbfb4f..46ee569 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
@@ -60,6 +60,8 @@
 import com.android.systemui.statusbar.policy.HotspotController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -71,8 +73,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import kotlinx.coroutines.test.TestScope;
-
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
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 c93ff4b..ea43326 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
@@ -32,7 +32,6 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.plugins.ActivityStarter;
@@ -42,6 +41,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.settings.SecureSettings;
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 954d30ed..a3c2975 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
@@ -41,7 +41,6 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.classifier.FalsingManagerFake;
@@ -51,6 +50,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.util.settings.FakeSettings;
 import com.android.systemui.util.settings.SecureSettings;
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 14dfdea..a85b49b6 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
@@ -31,7 +31,6 @@
 import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.internal.logging.MetricsLogger;
 import com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.plugins.ActivityStarter;
@@ -41,6 +40,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.HotspotController;
 
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 288facc..0ea61f9 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
@@ -17,6 +17,7 @@
 package com.android.systemui.qs.tiles;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -28,7 +29,6 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.plugins.ActivityStarter;
@@ -38,6 +38,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.qs.tiles.dialog.InternetDialogManager;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.connectivity.AccessPointController;
 import com.android.systemui.statusbar.connectivity.IconState;
 import com.android.systemui.statusbar.connectivity.NetworkController;
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 118ad2c..f6bc692 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
@@ -30,7 +30,6 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.classifier.FalsingManagerFake;
@@ -39,6 +38,7 @@
 import com.android.systemui.qs.QSHost;
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.res.R;
 
 import org.junit.After;
 import org.junit.Before;
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 7b3171d..d7beb5d 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
@@ -30,7 +30,6 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.plugins.ActivityStarter;
@@ -41,6 +40,7 @@
 import com.android.systemui.qs.QsEventLogger;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
 
 import org.junit.After;
 import org.junit.Before;
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 c5721ff..8eaa876 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
@@ -32,7 +32,6 @@
 
 import com.android.internal.R;
 import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.res.R.drawable;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.plugins.ActivityStarter;
@@ -43,6 +42,7 @@
 import com.android.systemui.qs.ReduceBrightColorsController;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R.drawable;
 import com.android.systemui.settings.UserTracker;
 
 import org.junit.After;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java
index b384fe8..2536a93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateControllerTest.java
@@ -5,6 +5,7 @@
 import static android.telephony.SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
 import static android.telephony.SignalStrength.SIGNAL_STRENGTH_GREAT;
 import static android.telephony.SignalStrength.SIGNAL_STRENGTH_POOR;
+
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.settingslib.wifi.WifiUtils.getHotspotIconResource;
 import static com.android.systemui.qs.tiles.dialog.InternetDialogController.TOAST_PARAMS_HORIZONTAL_WEIGHT;
@@ -12,7 +13,9 @@
 import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MAX;
 import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_MIN;
 import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
index 9e559de..2444af7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
@@ -17,9 +17,12 @@
 package com.android.systemui.screenrecord;
 
 import static android.os.Process.myUid;
+
 import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
index 10bd6af..4b7d5f0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/WorkProfileMessageControllerTest.java
@@ -38,10 +38,12 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.util.FakeSharedPreferences;
 
+import kotlin.Unit;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -51,9 +53,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-import kotlin.Unit;
-
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class WorkProfileMessageControllerTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
index 2c7b606..68a6893 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
@@ -47,8 +47,8 @@
 import androidx.test.runner.intercepting.SingleActivityFactory;
 
 import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.screenshot.ImageExporter;
 import com.android.systemui.settings.UserTracker;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
index 3d55527..6733ead 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
@@ -57,12 +57,12 @@
 import com.android.internal.infra.ServiceConnector;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.statusbar.IAppClipsService;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastSender;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.notetask.NoteTaskController;
+import com.android.systemui.res.R;
 
 import com.google.common.util.concurrent.MoreExecutors;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
index 03f5ecf..19b137c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
@@ -16,14 +16,13 @@
 
 package com.android.systemui.shade
 
-import android.content.Context
+import android.graphics.Rect
 import android.os.PowerManager
-import android.testing.AndroidTestingRunner
+import android.platform.test.flag.junit.FlagsParameterization
 import android.testing.TestableLooper
 import android.testing.ViewUtils
 import android.view.MotionEvent
 import android.view.View
-import android.view.WindowManager
 import android.widget.FrameLayout
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.LifecycleOwner
@@ -42,6 +41,7 @@
 import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
 import com.android.systemui.communal.util.CommunalColors
 import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.andSceneContainer
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
 import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
@@ -50,8 +50,10 @@
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.sceneDataSourceDelegator
-import com.android.systemui.shade.data.repository.fakeShadeRepository
 import com.android.systemui.shade.domain.interactor.shadeInteractor
 import com.android.systemui.statusbar.phone.SystemUIDialogFactory
 import com.android.systemui.testKosmos
@@ -70,12 +72,14 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
 
 @ExperimentalCoroutinesApi
-@RunWith(AndroidTestingRunner::class)
+@RunWith(ParameterizedAndroidJunit4::class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
-class GlanceableHubContainerControllerTest : SysuiTestCase() {
+class GlanceableHubContainerControllerTest(flags: FlagsParameterization?) : SysuiTestCase() {
     private val kosmos: Kosmos =
         testKosmos().apply {
             // UnconfinedTestDispatcher makes testing simpler due to CommunalInteractor flows using
@@ -97,6 +101,10 @@
     private lateinit var communalRepository: FakeCommunalRepository
     private lateinit var underTest: GlanceableHubContainerController
 
+    init {
+        mSetFlagsRule.setFlagsParameterization(flags!!)
+    }
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -132,6 +140,11 @@
         testableLooper = TestableLooper.get(this)
 
         overrideResource(R.dimen.communal_right_edge_swipe_region_width, RIGHT_SWIPE_REGION_WIDTH)
+        overrideResource(R.dimen.communal_top_edge_swipe_region_height, TOP_SWIPE_REGION_WIDTH)
+        overrideResource(
+            R.dimen.communal_bottom_edge_swipe_region_height,
+            BOTTOM_SWIPE_REGION_WIDTH
+        )
 
         // Make communal available so that communalInteractor.desiredScene accurately reflects
         // scene changes instead of just returning Blank.
@@ -247,7 +260,7 @@
                 goToScene(CommunalScenes.Communal)
 
                 // Shade shows up.
-                fakeShadeRepository.setQsExpansion(1.0f)
+                shadeTestUtil.setQsExpansion(1.0f)
                 testableLooper.processAllMessages()
 
                 // Touch events are not intercepted.
@@ -401,7 +414,7 @@
                 goToScene(CommunalScenes.Communal)
 
                 // Shade shows up.
-                fakeShadeRepository.setQsExpansion(1.0f)
+                shadeTestUtil.setQsExpansion(1.0f)
                 testableLooper.processAllMessages()
 
                 assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
@@ -421,6 +434,24 @@
             }
         }
 
+    @Test
+    fun gestureExclusionZone_setAfterInit() =
+        with(kosmos) {
+            testScope.runTest {
+                goToScene(CommunalScenes.Communal)
+
+                assertThat(containerView.systemGestureExclusionRects)
+                    .containsExactly(
+                        Rect(
+                            /* left */ 0,
+                            /* top */ TOP_SWIPE_REGION_WIDTH,
+                            /* right */ CONTAINER_WIDTH,
+                            /* bottom */ CONTAINER_HEIGHT - BOTTOM_SWIPE_REGION_WIDTH
+                        )
+                    )
+            }
+        }
+
     private fun initAndAttachContainerView() {
         containerView = View(context)
 
@@ -430,21 +461,19 @@
         underTest.initView(containerView)
 
         // Attach the view so that flows start collecting.
-        ViewUtils.attachView(parentView)
+        ViewUtils.attachView(parentView, CONTAINER_WIDTH, CONTAINER_HEIGHT)
         // Attaching is async so processAllMessages is required for view.repeatWhenAttached to run.
         testableLooper.processAllMessages()
-
-        // Give the view a fixed size to simplify testing for edge swipes.
-        val lp =
-            parentView.layoutParams.apply {
-                width = CONTAINER_WIDTH
-                height = CONTAINER_HEIGHT
-            }
-        val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
-        wm.updateViewLayout(parentView, lp)
     }
 
     private fun goToScene(scene: SceneKey) {
+        if (SceneContainerFlag.isEnabled) {
+            if (scene == CommunalScenes.Communal) {
+                kosmos.sceneInteractor.changeScene(Scenes.Communal, "test")
+            } else {
+                kosmos.sceneInteractor.changeScene(Scenes.Lockscreen, "test")
+            }
+        }
         communalRepository.changeScene(scene)
         testableLooper.processAllMessages()
     }
@@ -453,6 +482,8 @@
         private const val CONTAINER_WIDTH = 100
         private const val CONTAINER_HEIGHT = 100
         private const val RIGHT_SWIPE_REGION_WIDTH = 20
+        private const val TOP_SWIPE_REGION_WIDTH = 12
+        private const val BOTTOM_SWIPE_REGION_WIDTH = 14
 
         /**
          * A touch down event right in the middle of the screen, to avoid being in any of the swipe
@@ -471,5 +502,11 @@
             MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, CONTAINER_WIDTH.toFloat(), 0f, 0)
         private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
         private val UP_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
+
+        @JvmStatic
+        @Parameters(name = "{0}")
+        fun getParams(): List<FlagsParameterization> {
+            return FlagsParameterization.allCombinationsOf().andSceneContainer()
+        }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index d5e88fe..3793970 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -23,6 +23,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
@@ -37,9 +40,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
-import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
-
 import android.annotation.IdRes;
 import android.content.ContentResolver;
 import android.content.res.Configuration;
@@ -202,6 +202,9 @@
 
 import dagger.Lazy;
 
+import kotlinx.coroutines.CoroutineDispatcher;
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.After;
 import org.junit.Before;
 import org.mockito.ArgumentCaptor;
@@ -213,9 +216,6 @@
 import java.util.List;
 import java.util.Optional;
 
-import kotlinx.coroutines.CoroutineDispatcher;
-import kotlinx.coroutines.test.TestScope;
-
 public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
 
     protected static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
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 d95cc2e..112829a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
 package com.android.systemui.shade
 
 import android.content.Context
-import android.testing.AndroidTestingRunner
+import android.platform.test.flag.junit.FlagsParameterization
 import android.testing.TestableLooper.RunWithLooper
 import android.view.KeyEvent
 import android.view.MotionEvent
@@ -35,9 +35,11 @@
 import com.android.systemui.classifier.FalsingCollectorFake
 import com.android.systemui.dock.DockManager
 import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.DisableSceneContainer
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED
 import com.android.systemui.flags.Flags.SPLIT_SHADE_SUBPIXEL_OPTIMIZATION
+import com.android.systemui.flags.andSceneContainer
 import com.android.systemui.keyevent.domain.interactor.SysUIKeyEventHandler
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -45,6 +47,7 @@
 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
 import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
 import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
 import com.android.systemui.statusbar.DragDownHelper
@@ -69,11 +72,13 @@
 import com.android.systemui.util.mockito.eq
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
+import java.util.Optional
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.emptyFlow
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Ignore
 import org.junit.Test
@@ -86,15 +91,15 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
-import kotlin.test.assertEquals
-import java.util.Optional
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
 import org.mockito.Mockito.`when` as whenever
 
 @OptIn(ExperimentalCoroutinesApi::class)
 @SmallTest
-@RunWith(AndroidTestingRunner::class)
+@RunWith(ParameterizedAndroidJunit4::class)
 @RunWithLooper(setAsMainLooper = true)
-class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
+class NotificationShadeWindowViewControllerTest(flags: FlagsParameterization?) : SysuiTestCase() {
 
     @Mock private lateinit var view: NotificationShadeWindowView
     @Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
@@ -128,7 +133,7 @@
     @Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
     @Mock
     private lateinit var unfoldTransitionProgressProvider:
-        Optional<UnfoldTransitionProgressProvider>
+            Optional<UnfoldTransitionProgressProvider>
     @Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
     @Mock lateinit var dragDownHelper: DragDownHelper
     @Mock lateinit var mSelectedUserInteractor: SelectedUserInteractor
@@ -150,23 +155,29 @@
 
     private lateinit var featureFlagsClassic: FakeFeatureFlagsClassic
 
+    init {
+        mSetFlagsRule.setFlagsParameterization(flags!!)
+    }
+
     @Before
     fun setUp() {
         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)
+                .thenReturn(keyguardSecurityContainerController)
         whenever(keyguardTransitionInteractor.transition(LOCKSCREEN, DREAMING))
-            .thenReturn(emptyFlow<TransitionStep>())
+                .thenReturn(emptyFlow<TransitionStep>())
 
         featureFlagsClassic = FakeFeatureFlagsClassic()
         featureFlagsClassic.set(SPLIT_SHADE_SUBPIXEL_OPTIMIZATION, true)
         featureFlagsClassic.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false)
-        mSetFlagsRule.disableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
+        if (!SceneContainerFlag.isEnabled) {
+            mSetFlagsRule.disableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
+        }
         mSetFlagsRule.enableFlags(Flags.FLAG_REVAMPED_BOUNCER_MESSAGES)
 
         testScope = TestScope()
@@ -269,7 +280,7 @@
             whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
             whenever(panelExpansionInteractor.isFullyCollapsed).thenReturn(true)
             whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
-                .thenReturn(true)
+                    .thenReturn(true)
             whenever(phoneStatusBarViewController.sendTouchToView(DOWN_EVENT)).thenReturn(true)
 
             val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
@@ -284,7 +295,7 @@
             underTest.setStatusBarViewController(phoneStatusBarViewController)
             whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
             whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
-                .thenReturn(true)
+                    .thenReturn(true)
             // Item we're testing
             whenever(panelExpansionInteractor.isFullyCollapsed).thenReturn(false)
 
@@ -302,7 +313,7 @@
             whenever(panelExpansionInteractor.isFullyCollapsed).thenReturn(true)
             // Item we're testing
             whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
-                .thenReturn(false)
+                    .thenReturn(false)
 
             val returnVal = interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
 
@@ -316,7 +327,7 @@
             underTest.setStatusBarViewController(phoneStatusBarViewController)
             whenever(panelExpansionInteractor.isFullyCollapsed).thenReturn(true)
             whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
-                .thenReturn(true)
+                    .thenReturn(true)
             // Item we're testing
             whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(false)
 
@@ -333,7 +344,7 @@
             whenever(statusBarWindowStateController.windowIsShowing()).thenReturn(true)
             whenever(panelExpansionInteractor.isFullyCollapsed).thenReturn(true)
             whenever(phoneStatusBarViewController.touchIsWithinView(anyFloat(), anyFloat()))
-                .thenReturn(true)
+                    .thenReturn(true)
 
             // Down event first
             interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
@@ -354,7 +365,7 @@
             // GIVEN touch dispatcher in a state that returns true
             underTest.setStatusBarViewController(phoneStatusBarViewController)
             whenever(keyguardUnlockAnimationController.isPlayingCannedUnlockAnimation())
-                .thenReturn(true)
+                    .thenReturn(true)
             assertThat(interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)).isTrue()
 
             // WHEN launch animation is running for 2 seconds
@@ -375,6 +386,7 @@
         }
 
     @Test
+    @DisableSceneContainer
     fun handleDispatchTouchEvent_nsslMigrationOff_userActivity_not_called() {
         mSetFlagsRule.disableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
         underTest.setStatusBarViewController(phoneStatusBarViewController)
@@ -386,7 +398,7 @@
 
     @Test
     fun handleDispatchTouchEvent_nsslMigrationOn_userActivity() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+        enableMigrateClocksFlag()
         underTest.setStatusBarViewController(phoneStatusBarViewController)
 
         interactionEventHandler.handleDispatchTouchEvent(DOWN_EVENT)
@@ -408,7 +420,7 @@
     fun shouldInterceptTouchEvent_statusBarKeyguardViewManagerShouldIntercept() {
         // down event should be intercepted by keyguardViewManager
         whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
-            .thenReturn(true)
+                .thenReturn(true)
 
         // Then touch should not be intercepted
         val shouldIntercept = interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)
@@ -421,14 +433,14 @@
         whenever(sysuiStatusBarStateController.isDozing).thenReturn(true)
         // AND alternate bouncer doesn't want the touch
         whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
-            .thenReturn(false)
+                .thenReturn(false)
         // AND quick settings controller doesn't want it
         whenever(quickSettingsController.shouldQuickSettingsIntercept(any(), any(), any()))
-            .thenReturn(false)
+                .thenReturn(false)
         // AND the lock icon wants the touch
         whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT)).thenReturn(true)
 
-        mSetFlagsRule.enableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+        enableMigrateClocksFlag()
 
         // THEN touch should NOT be intercepted by NotificationShade
         assertThat(interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)).isFalse()
@@ -440,14 +452,14 @@
         whenever(sysuiStatusBarStateController.isDozing).thenReturn(true)
         // AND alternate bouncer doesn't want the touch
         whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
-            .thenReturn(false)
+                .thenReturn(false)
         // AND the lock icon does NOT want the touch
         whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT)).thenReturn(false)
         // AND quick settings controller doesn't want it
         whenever(quickSettingsController.shouldQuickSettingsIntercept(any(), any(), any()))
-            .thenReturn(false)
+                .thenReturn(false)
 
-        mSetFlagsRule.enableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+        enableMigrateClocksFlag()
 
         // THEN touch should be intercepted by NotificationShade
         assertThat(interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)).isTrue()
@@ -459,14 +471,14 @@
         whenever(sysuiStatusBarStateController.isDozing).thenReturn(true)
         // AND alternate bouncer doesn't want the touch
         whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
-            .thenReturn(false)
+                .thenReturn(false)
         // AND the lock icon does NOT want the touch
         whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT)).thenReturn(false)
         // AND quick settings controller DOES want it
         whenever(quickSettingsController.shouldQuickSettingsIntercept(any(), any(), any()))
-            .thenReturn(true)
+                .thenReturn(true)
 
-        mSetFlagsRule.enableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+        enableMigrateClocksFlag()
 
         // THEN touch should be intercepted by NotificationShade
         assertThat(interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)).isTrue()
@@ -480,20 +492,20 @@
         whenever(dozeServiceHost.isPulsing()).thenReturn(true)
         // AND status bar doesn't want it
         whenever(statusBarKeyguardViewManager.shouldInterceptTouchEvent(DOWN_EVENT))
-            .thenReturn(false)
+                .thenReturn(false)
         // AND shade is not fully expanded (mock is false by default)
         // AND the lock icon does NOT want the touch
         whenever(lockIconViewController.willHandleTouchWhileDozing(DOWN_EVENT)).thenReturn(false)
         // AND quick settings controller DOES want it
         whenever(quickSettingsController.shouldQuickSettingsIntercept(any(), any(), any()))
-            .thenReturn(true)
+                .thenReturn(true)
         // AND bouncer is not showing
         whenever(centralSurfaces.isBouncerShowing()).thenReturn(false)
         // AND panel view controller wants it
         whenever(shadeViewController.handleExternalInterceptTouch(DOWN_EVENT))
-            .thenReturn(true)
+                .thenReturn(true)
 
-        mSetFlagsRule.enableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+        enableMigrateClocksFlag()
 
         // THEN touch should be intercepted by NotificationShade
         assertThat(interactionEventHandler.shouldInterceptTouchEvent(DOWN_EVENT)).isTrue()
@@ -550,11 +562,11 @@
     @Ignore("b/321332798")
     fun setsUpCommunalHubLayout_whenFlagEnabled() {
         whenever(mGlanceableHubContainerController.communalAvailable())
-            .thenReturn(MutableStateFlow(true))
+                .thenReturn(MutableStateFlow(true))
 
         val mockCommunalView = mock(View::class.java)
         whenever(mGlanceableHubContainerController.initView(any<Context>()))
-            .thenReturn(mockCommunalView)
+                .thenReturn(mockCommunalView)
 
         val mockCommunalPlaceholder = mock(View::class.java)
         val fakeViewIndex = 20
@@ -572,7 +584,7 @@
     @Test
     fun doesNotSetupCommunalHubLayout_whenFlagDisabled() {
         whenever(mGlanceableHubContainerController.communalAvailable())
-            .thenReturn(MutableStateFlow(false))
+                .thenReturn(MutableStateFlow(false))
 
         val mockCommunalPlaceholder = mock(View::class.java)
         val fakeViewIndex = 20
@@ -616,15 +628,27 @@
 
     @Test
     fun cancelCurrentTouch_callsDragDownHelper() {
-        mSetFlagsRule.enableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+        enableMigrateClocksFlag()
         underTest.cancelCurrentTouch()
 
         verify(dragDownHelper).stopDragging()
     }
 
+    private fun enableMigrateClocksFlag() {
+        if (!Flags.migrateClocksToBlueprint()) {
+            mSetFlagsRule.enableFlags(Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
+        }
+    }
+
     companion object {
         private val DOWN_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)
         private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
         private const val VIEW_BOTTOM = 100
+
+        @JvmStatic
+        @Parameters(name = "{0}")
+        fun getParams(): List<FlagsParameterization> {
+            return FlagsParameterization.allCombinationsOf().andSceneContainer()
+        }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
index 0f51878..317e35c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerImplBaseTest.java
@@ -16,14 +16,14 @@
 
 package com.android.systemui.shade;
 
+import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
+import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
-import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
-
 import android.content.res.Resources;
 import android.os.Handler;
 import android.os.Looper;
@@ -98,13 +98,13 @@
 
 import dagger.Lazy;
 
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.After;
 import org.junit.Before;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import kotlinx.coroutines.test.TestScope;
-
 public class QuickSettingsControllerImplBaseTest extends SysuiTestCase {
     protected static final float QS_FRAME_START_X = 0f;
     protected static final int QS_FRAME_WIDTH = 1000;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
index 9fa173a..0846ced 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ShadeHeaderControllerTest.kt
@@ -22,6 +22,7 @@
 import android.content.Context
 import android.content.res.Resources
 import android.content.res.XmlResourceParser
+import android.graphics.Insets
 import android.graphics.Rect
 import android.testing.AndroidTestingRunner
 import android.view.Display
@@ -35,7 +36,6 @@
 import androidx.constraintlayout.widget.ConstraintSet
 import androidx.test.filters.SmallTest
 import com.android.app.animation.Interpolators
-import com.android.systemui.res.R
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.animation.ShadeInterpolation
 import com.android.systemui.battery.BatteryMeterView
@@ -46,6 +46,7 @@
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.qs.ChipVisibilityListener
 import com.android.systemui.qs.HeaderPrivacyIconsController
+import com.android.systemui.res.R
 import com.android.systemui.shade.ShadeHeaderController.Companion.DEFAULT_CLOCK_INTENT
 import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_HEADER_CONSTRAINT
 import com.android.systemui.shade.ShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
@@ -53,9 +54,10 @@
 import com.android.systemui.shade.carrier.ShadeCarrierGroup
 import com.android.systemui.shade.carrier.ShadeCarrierGroupController
 import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
-import com.android.systemui.statusbar.phone.StatusBarIconController
 import com.android.systemui.statusbar.phone.StatusIconContainer
 import com.android.systemui.statusbar.phone.StatusOverlayHoverListenerFactory
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController
+import com.android.systemui.statusbar.phone.ui.TintedIconManager
 import com.android.systemui.statusbar.policy.Clock
 import com.android.systemui.statusbar.policy.FakeConfigurationController
 import com.android.systemui.statusbar.policy.NextAlarmController
@@ -83,7 +85,6 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.Mockito.`when` as whenever
-import android.graphics.Insets
 import org.mockito.junit.MockitoJUnit
 
 private val EMPTY_CHANGES = ConstraintsChanges()
@@ -95,8 +96,8 @@
     @Mock(answer = Answers.RETURNS_MOCKS) private lateinit var view: MotionLayout
     @Mock private lateinit var statusIcons: StatusIconContainer
     @Mock private lateinit var statusBarIconController: StatusBarIconController
-    @Mock private lateinit var iconManagerFactory: StatusBarIconController.TintedIconManager.Factory
-    @Mock private lateinit var iconManager: StatusBarIconController.TintedIconManager
+    @Mock private lateinit var iconManagerFactory: TintedIconManager.Factory
+    @Mock private lateinit var iconManager: TintedIconManager
     @Mock private lateinit var mShadeCarrierGroupController: ShadeCarrierGroupController
     @Mock
     private lateinit var mShadeCarrierGroupControllerBuilder: ShadeCarrierGroupController.Builder
@@ -145,12 +146,14 @@
         whenever<TextView>(view.requireViewById(R.id.date)).thenReturn(date)
         whenever(date.context).thenReturn(mockedContext)
 
-        whenever<ShadeCarrierGroup>(view.requireViewById(R.id.carrier_group)).thenReturn(carrierGroup)
+        whenever<ShadeCarrierGroup>(view.requireViewById(R.id.carrier_group))
+            .thenReturn(carrierGroup)
 
         whenever<BatteryMeterView>(view.requireViewById(R.id.batteryRemainingIcon))
             .thenReturn(batteryMeterView)
 
-        whenever<StatusIconContainer>(view.requireViewById(R.id.statusIcons)).thenReturn(statusIcons)
+        whenever<StatusIconContainer>(view.requireViewById(R.id.statusIcons))
+            .thenReturn(statusIcons)
         whenever<View>(view.requireViewById(R.id.hover_system_icons_container))
             .thenReturn(systemIconsHoverContainer)
 
@@ -933,14 +936,14 @@
 
     private fun mockInsetsProvider(insets: Pair<Int, Int> = 0 to 0, cornerCutout: Boolean = false) {
         whenever(insetsProvider.getStatusBarContentInsetsForCurrentRotation())
-                .thenReturn(
-                        Insets.of(
-                                /* left= */ insets.first,
-                                /* top= */ 0,
-                                /* right= */ insets.second,
-                                /* bottom= */ 0
-                        )
+            .thenReturn(
+                Insets.of(
+                    /* left= */ insets.first,
+                    /* top= */ 0,
+                    /* right= */ insets.second,
+                    /* bottom= */ 0
                 )
+            )
         whenever(insetsProvider.currentRotationHasCornerCutout()).thenReturn(cornerCutout)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java
index e7056c7..4c2d908 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java
@@ -62,6 +62,8 @@
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 import com.android.systemui.utils.os.FakeHandler;
 
+import kotlinx.coroutines.flow.MutableStateFlow;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -73,8 +75,6 @@
 import java.util.Arrays;
 import java.util.List;
 
-import kotlinx.coroutines.flow.MutableStateFlow;
-
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 @SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java
index a657edf..a42121a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/carrier/ShadeCarrierTest.java
@@ -31,8 +31,8 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.settingslib.mobile.TelephonyIcons;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
index 0b1753f..65ca0a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
@@ -36,6 +36,8 @@
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -48,8 +50,6 @@
 import java.util.Collections;
 import java.util.HashSet;
 
-import kotlinx.coroutines.CoroutineScope;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class ConditionMonitorTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java
index 6efade9..cec5d0a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java
@@ -31,14 +31,14 @@
 
 import com.android.systemui.SysuiTestCase;
 
+import kotlinx.coroutines.CoroutineScope;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import kotlinx.coroutines.CoroutineScope;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class ConditionTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
index 544860e..775dc3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -36,9 +36,9 @@
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.IStatusBarService;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.res.R;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index 5abad61..63ce233 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -30,6 +30,7 @@
 import android.os.Bundle
 import android.os.Handler
 import android.os.UserHandle
+import android.platform.test.annotations.DisableFlags
 import android.provider.Settings
 import android.view.View
 import android.widget.FrameLayout
@@ -49,11 +50,14 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.smartspace.ui.viewmodel.SmartspaceViewModel
+import com.android.systemui.smartspace.viewmodel.smartspaceViewModelFactory
 import com.android.systemui.statusbar.phone.KeyguardBypassController
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener
+import com.android.systemui.testKosmos
 import com.android.systemui.util.concurrency.FakeExecution
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.mockito.any
@@ -182,6 +186,7 @@
     private lateinit var weatherSmartspaceView: SmartspaceView
     private lateinit var smartspaceView: SmartspaceView
     private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+    private lateinit var smartspaceViewModelFactory: SmartspaceViewModel.Factory
 
     private val clock = FakeSystemClock()
     private val executor = FakeExecutor(clock)
@@ -234,6 +239,7 @@
             clock,
             dumpManager
         )
+        smartspaceViewModelFactory = testKosmos().smartspaceViewModelFactory
 
         controller = LockscreenSmartspaceController(
                 context,
@@ -251,6 +257,7 @@
                 keyguardBypassController,
                 keyguardUpdateMonitor,
                 wakefulnessLifecycle,
+                smartspaceViewModelFactory,
                 dumpManager,
                 execution,
                 executor,
@@ -785,6 +792,7 @@
     }
 
     @Test
+    @DisableFlags(com.android.systemui.Flags.FLAG_SMARTSPACE_LOCKSCREEN_VIEWMODEL)
     fun testWakefulnessLifecycleDispatch_wake_setsSmartspaceScreenOnTrue() {
         // Connect session
         connectSession()
@@ -801,6 +809,7 @@
     }
 
     @Test
+    @DisableFlags(com.android.systemui.Flags.FLAG_SMARTSPACE_LOCKSCREEN_VIEWMODEL)
     fun testWakefulnessLifecycleDispatch_sleep_setsSmartspaceScreenOnFalse() {
         // Connect session
         connectSession()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
index eafa78e..0103564 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/DynamicChildBindControllerTest.java
@@ -55,7 +55,6 @@
 import java.util.List;
 import java.util.Map;
 
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
index af52459..3676a3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinatorTest.java
@@ -27,7 +27,6 @@
 import android.app.ActivityManagerInternal;
 import android.app.Notification;
 import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.RemoteException;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
index 6f0a19d..50ae985 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
@@ -20,6 +20,8 @@
 
 import static junit.framework.Assert.assertFalse;
 
+import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
+
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
@@ -29,8 +31,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
-
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
@@ -62,6 +62,9 @@
 import com.android.systemui.util.kotlin.JavaAdapter;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import kotlinx.coroutines.flow.MutableStateFlow;
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -71,9 +74,6 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.verification.VerificationMode;
 
-import kotlinx.coroutines.flow.MutableStateFlow;
-import kotlinx.coroutines.test.TestScope;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
index 6bda4d4..a21ca94 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/footer/ui/view/FooterViewTest.java
@@ -50,11 +50,11 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.util.List;
-
 import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
 import platform.test.runner.parameterized.Parameters;
 
+import java.util.List;
+
 @SmallTest
 @RunWith(ParameterizedAndroidJunit4.class)
 public class FooterViewTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
index 06410cd..8662048 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProviderTest.java
@@ -55,7 +55,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FakeFeatureFlagsClassic;
 import com.android.systemui.flags.FeatureFlagsClassic;
-import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index bb68ec5..1113091 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification.logging;
 
+import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
+
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -28,8 +30,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
-
 import android.app.Notification;
 import android.os.Handler;
 import android.os.Looper;
@@ -72,6 +72,8 @@
 
 import com.google.android.collect.Lists;
 
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -84,8 +86,6 @@
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.Executor;
 
-import kotlinx.coroutines.test.TestScope;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
index bdc8135..9d2f32d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragControllerTest.java
@@ -47,7 +47,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 9e2856d..907649b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -28,6 +28,8 @@
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertTrue;
 
+import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
@@ -42,8 +44,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
-
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
@@ -98,6 +98,8 @@
 import com.android.systemui.util.kotlin.JavaAdapter;
 import com.android.systemui.wmshell.BubblesManager;
 
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -109,8 +111,6 @@
 
 import java.util.Optional;
 
-import kotlinx.coroutines.test.TestScope;
-
 /**
  * Tests for {@link NotificationGutsManager}.
  */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java
index edf2b4c..180c8c8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java
@@ -18,8 +18,6 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertSame;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -37,8 +35,6 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import java.io.IOException;
-
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class NotificationInlineImageResolverTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index f35ec74..1661860 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -99,6 +99,10 @@
 import com.android.systemui.wmshell.BubblesManager;
 import com.android.systemui.wmshell.BubblesTestActivity;
 
+import kotlin.coroutines.CoroutineContext;
+
+import kotlinx.coroutines.test.TestScope;
+
 import org.mockito.ArgumentCaptor;
 
 import java.util.Objects;
@@ -107,9 +111,6 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 
-import kotlin.coroutines.CoroutineContext;
-import kotlinx.coroutines.test.TestScope;
-
 /**
  * A helper class to create {@link ExpandableNotificationRow} (for both individual and group
  * notifications).
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
index e3a77d3..fad85f53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
@@ -21,8 +21,6 @@
 
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.TextView;
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 041e61c..f666d8e 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
@@ -27,6 +27,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static kotlinx.coroutines.flow.FlowKt.flowOf;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -44,8 +46,6 @@
 
 import static java.util.Collections.emptySet;
 
-import static kotlinx.coroutines.flow.FlowKt.flowOf;
-
 import android.app.ActivityManager;
 import android.app.IWallpaperManager;
 import android.app.WallpaperManager;
@@ -195,6 +195,8 @@
 
 import dagger.Lazy;
 
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -208,8 +210,6 @@
 
 import javax.inject.Provider;
 
-import kotlinx.coroutines.test.TestScope;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
index a6a4f24..8e9840a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.java
@@ -59,8 +59,8 @@
 import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
 import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
-import com.android.systemui.flags.FakeFeatureFlagsClassic;
-import com.android.systemui.flags.Flags;
+import com.android.systemui.flags.DisableSceneContainer;
+import com.android.systemui.flags.EnableSceneContainer;
 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
@@ -76,6 +76,8 @@
 import com.android.systemui.statusbar.data.repository.FakeKeyguardStatusBarRepository;
 import com.android.systemui.statusbar.domain.interactor.KeyguardStatusBarInteractor;
 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
+import com.android.systemui.statusbar.phone.ui.TintedIconManager;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -87,6 +89,8 @@
 import com.android.systemui.util.settings.SecureSettings;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -95,13 +99,10 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import kotlinx.coroutines.test.TestScope;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 public class KeyguardStatusBarViewControllerTest extends SysuiTestCase {
-    private final FakeFeatureFlagsClassic mFeatureFlags = new FakeFeatureFlagsClassic();
     @Mock
     private CarrierTextController mCarrierTextController;
     @Mock
@@ -115,9 +116,9 @@
     @Mock
     private StatusBarIconController mStatusBarIconController;
     @Mock
-    private StatusBarIconController.TintedIconManager.Factory mIconManagerFactory;
+    private TintedIconManager.Factory mIconManagerFactory;
     @Mock
-    private StatusBarIconController.TintedIconManager mIconManager;
+    private TintedIconManager mIconManager;
     @Mock
     private BatteryMeterViewController mBatteryMeterViewController;
     @Mock
@@ -160,7 +161,6 @@
 
     @Before
     public void setup() throws Exception {
-        mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, false);
         mShadeViewStateProvider = new TestShadeViewStateProvider();
 
         MockitoAnnotations.initMocks(this);
@@ -217,7 +217,6 @@
                 mBiometricUnlockController,
                 mStatusBarStateController,
                 mStatusBarContentInsetsProvider,
-                mFeatureFlags,
                 mUserManager,
                 mStatusBarUserChipViewModel,
                 mSecureSettings,
@@ -334,8 +333,8 @@
     }
 
     @Test
+    @DisableSceneContainer
     public void onViewReAttached_flagOff_iconManagerNotReRegistered() {
-        mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, false);
         mController.onViewAttached();
         mController.onViewDetached();
         reset(mStatusBarIconController);
@@ -346,8 +345,8 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void onViewReAttached_flagOn_iconManagerReRegistered() {
-        mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, true);
         mController.onViewAttached();
         mController.onViewDetached();
         reset(mStatusBarIconController);
@@ -383,9 +382,8 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void setBatteryListening_true_flagOn_callbackNotAdded() {
-        mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, true);
-
         mController.setBatteryListening(true);
 
         verify(mBatteryController, never()).addCallback(any());
@@ -563,8 +561,8 @@
     }
 
     @Test
+    @DisableSceneContainer
     public void updateViewState_dozingTrue_flagOff_viewHidden() {
-        mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, false);
         mController.init();
         mController.onViewAttached();
         updateStateToKeyguard();
@@ -576,8 +574,8 @@
     }
 
     @Test
+    @DisableSceneContainer
     public void updateViewState_dozingFalse_flagOff_viewShown() {
-        mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, false);
         mController.init();
         mController.onViewAttached();
         updateStateToKeyguard();
@@ -589,8 +587,8 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void updateViewState_flagOn_doesNothing() {
-        mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, true);
         mController.init();
         mController.onViewAttached();
         updateStateToKeyguard();
@@ -605,8 +603,8 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void updateViewStateWithAlphaAndVis_flagOn_doesNothing() {
-        mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, true);
         mController.init();
         mController.onViewAttached();
         updateStateToKeyguard();
@@ -621,8 +619,8 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void setAlpha_flagOn_doesNothing() {
-        mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, true);
         mController.init();
         mController.onViewAttached();
         updateStateToKeyguard();
@@ -635,8 +633,8 @@
     }
 
     @Test
+    @EnableSceneContainer
     public void setDozing_flagOn_doesNothing() {
-        mFeatureFlags.set(Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, true);
         mController.init();
         mController.onViewAttached();
         updateStateToKeyguard();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewTest.java
index e88fd95..c44f979 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewTest.java
@@ -25,8 +25,8 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 
 import org.junit.Before;
 import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
index f6419a9..7271a5e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
@@ -55,6 +55,8 @@
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.util.kotlin.JavaAdapter;
 
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -64,8 +66,6 @@
 import java.util.Arrays;
 import java.util.List;
 
-import kotlinx.coroutines.test.TestScope;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java
index d25a06b..ccd1a8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationTapHelperTest.java
@@ -29,9 +29,9 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.res.R;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
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 7deee5a..8d2c158 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
@@ -36,6 +36,7 @@
 import com.android.systemui.screenrecord.RecordingController
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController
 import com.android.systemui.statusbar.policy.BluetoothController
 import com.android.systemui.statusbar.policy.CastController
 import com.android.systemui.statusbar.policy.DataSaverController
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 f947640..1000329 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.junit.Assert.assertFalse;
 import static org.mockito.ArgumentMatchers.any;
@@ -41,8 +43,6 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
-
 import android.animation.Animator;
 import android.app.AlarmManager;
 import android.content.Context;
@@ -89,6 +89,8 @@
 
 import com.google.common.truth.Expect;
 
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -105,8 +107,6 @@
 import java.util.HashSet;
 import java.util.Map;
 
-import kotlinx.coroutines.test.TestScope;
-
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 @SmallTest
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 f04a5ab..e38e31d 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
@@ -19,6 +19,8 @@
 import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
 import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE;
 
+import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
+
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -35,8 +37,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
-
 import android.platform.test.annotations.RequiresFlagsEnabled;
 import android.platform.test.flag.junit.CheckFlagsRule;
 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 9c3d9c6..66211c9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -61,10 +61,11 @@
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
 import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
+import com.android.systemui.statusbar.phone.ui.DarkIconManager;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeCollapsedStatusBarViewBinder;
 import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.FakeCollapsedStatusBarViewModel;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -117,9 +118,9 @@
     @Mock
     private PanelExpansionInteractor mPanelExpansionInteractor;
     @Mock
-    private StatusBarIconController.DarkIconManager.Factory mIconManagerFactory;
+    private DarkIconManager.Factory mIconManagerFactory;
     @Mock
-    private StatusBarIconController.DarkIconManager mIconManager;
+    private DarkIconManager mIconManager;
     private FakeCollapsedStatusBarViewModel mCollapsedStatusBarViewModel;
     private FakeCollapsedStatusBarViewBinder mCollapsedStatusBarViewBinder;
     @Mock
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImplTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt
index f6a8243..617c553 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImplTest.kt
@@ -14,15 +14,16 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone
+package com.android.systemui.statusbar.phone.ui
 
 import android.os.UserHandle
 import androidx.test.filters.SmallTest
 import com.android.internal.statusbar.StatusBarIcon
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.statusbar.CommandQueue
-import com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY
-import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl.EXTERNAL_SLOT_SUFFIX
+import com.android.systemui.statusbar.phone.StatusBarIconHolder
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController.TAG_PRIMARY
+import com.android.systemui.statusbar.phone.ui.StatusBarIconControllerImpl.EXTERNAL_SLOT_SUFFIX
 import com.android.systemui.statusbar.pipeline.icons.shared.BindableIconsRegistry
 import com.android.systemui.statusbar.pipeline.icons.shared.model.BindableIcon
 import com.android.systemui.statusbar.pipeline.icons.shared.model.ModernStatusBarViewCreator
@@ -42,7 +43,7 @@
 
     private lateinit var iconList: StatusBarIconList
     private lateinit var commandQueueCallbacks: CommandQueue.Callbacks
-    private val iconGroup: StatusBarIconController.IconManager = mock()
+    private val iconGroup: IconManager = mock()
 
     @Mock private lateinit var commandQueue: CommandQueue
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java
similarity index 84%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java
index ca31623..14bce9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerTest.java
@@ -1,20 +1,20 @@
 /*
  * Copyright (C) 2017 The Android Open Source Project
  *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
  *
  *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
-
-import static com.android.systemui.statusbar.phone.StatusBarIconHolder.TYPE_ICON;
+package com.android.systemui.statusbar.phone.ui;
 
 import static junit.framework.Assert.assertTrue;
 
@@ -40,8 +40,8 @@
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.StatusIconDisplayable;
 import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
-import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
-import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
+import com.android.systemui.statusbar.phone.StatusBarIconHolder;
+import com.android.systemui.statusbar.phone.StatusBarLocation;
 import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
 import com.android.systemui.statusbar.pipeline.icons.shared.BindableIconsRegistry;
 import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter;
@@ -60,9 +60,9 @@
 @SmallTest
 public class StatusBarIconControllerTest extends LeakCheckedTest {
 
-    private MobileContextProvider mMobileContextProvider = mock(MobileContextProvider.class);
-    private MobileUiAdapter mMobileUiAdapter = mock(MobileUiAdapter.class);
-    private MobileIconsViewModel mMobileIconsViewModel = mock(MobileIconsViewModel.class);
+    private final MobileContextProvider mMobileContextProvider = mock(MobileContextProvider.class);
+    private final MobileUiAdapter mMobileUiAdapter = mock(MobileUiAdapter.class);
+    private final MobileIconsViewModel mMobileIconsViewModel = mock(MobileIconsViewModel.class);
 
     @Before
     public void setup() {
@@ -123,22 +123,13 @@
     }
 
     private <T extends IconManager & TestableIconManager> void testCallOnAdd_forManager(T manager) {
-        StatusBarIconHolder holder = holderForType(TYPE_ICON);
+        StatusBarIconHolder holder = StatusBarIconHolder.fromIcon(mock(StatusBarIcon.class));
         manager.onIconAdded(0, "test_slot", false, holder);
         assertTrue("Expected StatusBarIconView",
                 (manager.getViewAt(0) instanceof StatusBarIconView));
 
     }
 
-    private StatusBarIconHolder holderForType(int type) {
-        switch (type) {
-
-            case TYPE_ICON:
-            default:
-                return StatusBarIconHolder.fromIcon(mock(StatusBarIcon.class));
-        }
-    }
-
     private static class TestDarkIconManager extends DarkIconManager
             implements TestableIconManager {
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconListTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconListTest.java
similarity index 94%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconListTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconListTest.java
index f0a4f3f..02a6301 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconListTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ui/StatusBarIconListTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2022 The Android Open Source Project
+ * Copyright (C) 2024 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.statusbar.phone.ui;
 
-import static com.android.systemui.statusbar.phone.StatusBarIconController.TAG_PRIMARY;
+import static com.android.systemui.statusbar.phone.ui.StatusBarIconController.TAG_PRIMARY;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNull;
@@ -29,7 +29,9 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.phone.StatusBarIconList.Slot;
+import com.android.systemui.statusbar.phone.StatusBarIconHolder;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconList;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconList.Slot;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
index 9d14116..3695d8c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt
@@ -35,6 +35,7 @@
 import android.telephony.SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX
 import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET
 import android.telephony.TelephonyCallback
+import android.telephony.TelephonyCallback.CarrierRoamingNtnModeListener
 import android.telephony.TelephonyCallback.DataActivityListener
 import android.telephony.TelephonyCallback.DisplayInfoListener
 import android.telephony.TelephonyCallback.ServiceStateListener
@@ -983,26 +984,19 @@
 
     @Test
     @EnableFlags(com.android.internal.telephony.flags.Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG)
-    fun isNonTerrestrial_updatesFromServiceState() =
+    fun isNonTerrestrial_updatesFromCallback0() =
         testScope.runTest {
             val latest by collectLastValue(underTest.isNonTerrestrial)
 
-            // Lambda makes it a little clearer what we are testing IMO
-            val serviceStateCreator = { ntn: Boolean ->
-                mock<ServiceState>().also {
-                    whenever(it.isUsingNonTerrestrialNetwork).thenReturn(ntn)
-                }
-            }
-
             // Starts out false
             assertThat(latest).isFalse()
 
-            getTelephonyCallbackForType<ServiceStateListener>()
-                .onServiceStateChanged(serviceStateCreator(true))
+            val callback = getTelephonyCallbackForType<CarrierRoamingNtnModeListener>()
+
+            callback.onCarrierRoamingNtnModeChanged(true)
             assertThat(latest).isTrue()
 
-            getTelephonyCallbackForType<ServiceStateListener>()
-                .onServiceStateChanged(serviceStateCreator(false))
+            callback.onCarrierRoamingNtnModeChanged(false)
             assertThat(latest).isFalse()
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
index 3fae3f6..784fb71 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
@@ -38,9 +38,9 @@
 
 import androidx.test.filters.SmallTest;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
+import com.android.systemui.res.R;
 import com.android.systemui.settings.UserTracker;
 
 import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
index bf280c9..456723d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/InflatedSmartRepliesTest.java
@@ -37,8 +37,8 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
 import com.android.systemui.shared.system.PackageManagerWrapper;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
index 479309c..3a086ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
@@ -52,7 +52,6 @@
 
 import java.util.Random;
 
-
 @SmallTest
 @TestableLooper.RunWithLooper
 @RunWith(AndroidTestingRunner.class)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
index b9557d2..a9681e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyConstantsTest.java
@@ -21,7 +21,6 @@
 import static junit.framework.Assert.assertTrue;
 
 import android.app.RemoteInput;
-import android.os.Handler;
 import android.provider.DeviceConfig;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index 4b6c68a..a213c85 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -47,11 +47,11 @@
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.systemui.res.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.res.R;
 import com.android.systemui.shade.ShadeController;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.SmartReplyController;
@@ -60,6 +60,9 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
 
+import kotlin.sequences.Sequence;
+import kotlin.sequences.SequencesKt;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -76,9 +79,6 @@
 import java.util.stream.IntStream;
 import java.util.stream.Stream;
 
-import kotlin.sequences.Sequence;
-import kotlin.sequences.SequencesKt;
-
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 @SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectTest.kt
deleted file mode 100644
index 8105cc5..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/gloweffect/GlowPieEffectTest.kt
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.surfaceeffects.gloweffect
-
-import android.graphics.Color
-import android.graphics.RenderEffect
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.animation.AnimatorTestRule
-import com.android.systemui.model.SysUiStateTest
-import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
-import com.google.common.truth.Truth.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-class GlowPieEffectTest : SysUiStateTest() {
-
-    @get:Rule val animatorTestRule = AnimatorTestRule(this)
-
-    @Test
-    fun play_triggersDrawCallback() {
-        var effectFromCallback: RenderEffect? = null
-        val glowPieEffectConfig =
-            GlowPieEffectConfig(
-                centerX = 0f,
-                centerY = 0f,
-                width = 1f,
-                height = 1f,
-                cornerRadius = 0.5f,
-                colors = intArrayOf(Color.RED, Color.GREEN, Color.BLUE)
-            )
-        val drawCallback =
-            object : RenderEffectDrawCallback {
-                override fun onDraw(renderEffect: RenderEffect) {
-                    effectFromCallback = renderEffect
-                }
-            }
-        val glowPieEffect = GlowPieEffect(glowPieEffectConfig, drawCallback)
-
-        assertThat(effectFromCallback).isNull()
-
-        glowPieEffect.play()
-
-        animatorTestRule.advanceTimeBy(100L)
-
-        assertThat(effectFromCallback).isNotNull()
-    }
-
-    @Test
-    fun finish_cancelsAnimator() {
-        val glowPieEffectConfig =
-            GlowPieEffectConfig(
-                centerX = 0f,
-                centerY = 0f,
-                width = 1f,
-                height = 1f,
-                cornerRadius = 0.5f,
-                colors = intArrayOf(Color.RED, Color.GREEN, Color.BLUE)
-            )
-        val drawCallback =
-            object : RenderEffectDrawCallback {
-                override fun onDraw(renderEffect: RenderEffect) {}
-            }
-        val glowPieEffect = GlowPieEffect(glowPieEffectConfig, drawCallback)
-
-        glowPieEffect.play()
-        animatorTestRule.advanceTimeBy(100L)
-
-        assertThat(glowPieEffect.mainAnimator.isRunning).isTrue()
-
-        glowPieEffect.finish()
-
-        assertThat(glowPieEffect.mainAnimator.isRunning).isFalse()
-    }
-
-    @Test
-    fun glowPie_progress_computesProgressCorrectly() {
-        val myGlowPieConfig =
-            object : GlowPieEffect.GlowPie {
-                override val startMs: Float = 0f
-                override val endMs: Float = GlowPieEffect.DURATION_MS.toFloat()
-                override val startAngle: Float = 0f
-                override val endAngle: Float = 6f * GlowPieEffect.PI
-                override val alphaFadeStartMs: Float = 0f
-                override val alphaFadeEndMs: Float = GlowPieEffect.DURATION_MS.toFloat()
-                override var progress: Float = 0f
-                override var time: Float = 0f
-            }
-
-        val playTime = GlowPieEffect.DURATION_MS.toFloat() * 0.5f
-        val tolerance = 1e-4f
-        myGlowPieConfig.updateProgress(playTime)
-
-        assertThat(myGlowPieConfig.time).isWithin(tolerance).of(playTime)
-        assertThat(myGlowPieConfig.progress).isWithin(tolerance).of(0.5f)
-        assertThat(myGlowPieConfig.angle()).isWithin(tolerance).of(-3.5f * GlowPieEffect.PI)
-        assertThat(myGlowPieConfig.bottomThreshold())
-            .isWithin(tolerance)
-            .of((1f - GlowPieEffect.FEATHER) * 0.5f)
-        assertThat(myGlowPieConfig.topThreshold())
-            .isWithin(tolerance)
-            .of((1f + GlowPieEffect.FEATHER) * 0.5f)
-        assertThat(myGlowPieConfig.alpha()).isWithin(tolerance).of(0.5f)
-
-        myGlowPieConfig.resetProgress()
-
-        assertThat(myGlowPieConfig.time).isEqualTo(0f)
-        assertThat(myGlowPieConfig.progress).isEqualTo(0f)
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectTest.kt
deleted file mode 100644
index b1df159..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/revealeffect/RippleRevealEffectTest.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2024 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS 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.surfaceeffects.revealeffect
-
-import android.graphics.RenderEffect
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.animation.AnimatorTestRule
-import com.android.systemui.model.SysUiStateTest
-import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
-import com.google.common.truth.Truth.assertThat
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-class RippleRevealEffectTest : SysUiStateTest() {
-
-    @get:Rule val animatorTestRule = AnimatorTestRule(this)
-
-    @Test
-    fun play_triggersDrawCallback() {
-        var effectFromCallback: RenderEffect? = null
-        val revealEffectConfig = RippleRevealEffectConfig(duration = 1000f)
-        val drawCallback =
-            object : RenderEffectDrawCallback {
-                override fun onDraw(renderEffect: RenderEffect) {
-                    effectFromCallback = renderEffect
-                }
-            }
-        val revealEffect = RippleRevealEffect(revealEffectConfig, drawCallback)
-        assertThat(effectFromCallback).isNull()
-
-        revealEffect.play()
-
-        animatorTestRule.advanceTimeBy(500L)
-
-        assertThat(effectFromCallback).isNotNull()
-    }
-
-    @Test
-    fun play_triggersStateChangedCallback() {
-        val revealEffectConfig = RippleRevealEffectConfig(duration = 1000f)
-        val drawCallback =
-            object : RenderEffectDrawCallback {
-                override fun onDraw(renderEffect: RenderEffect) {}
-            }
-        var animationStartedCalled = false
-        var animationEndedCalled = false
-        val stateChangedCallback =
-            object : RippleRevealEffect.AnimationStateChangedCallback {
-                override fun onAnimationStart() {
-                    animationStartedCalled = true
-                }
-
-                override fun onAnimationEnd() {
-                    animationEndedCalled = true
-                }
-            }
-        val revealEffect =
-            RippleRevealEffect(revealEffectConfig, drawCallback, stateChangedCallback)
-
-        assertThat(animationStartedCalled).isFalse()
-        assertThat(animationEndedCalled).isFalse()
-
-        revealEffect.play()
-
-        assertThat(animationStartedCalled).isTrue()
-
-        animatorTestRule.advanceTimeBy(revealEffectConfig.duration.toLong())
-
-        assertThat(animationEndedCalled).isTrue()
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
index 31bad2c..9dfa14d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
@@ -29,6 +29,8 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.util.time.FakeSystemClock;
 
+import kotlin.jvm.functions.Function4;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -36,8 +38,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import kotlin.jvm.functions.Function4;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class FakeExecutorTest extends SysuiTestCase {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractorTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractorTest.java
index 0eba21a..33d09c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/WallpaperLocalColorExtractorTest.java
@@ -59,8 +59,8 @@
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 public class WallpaperLocalColorExtractorTest extends SysuiTestCase {
-    private static final int LOW_BMP_WIDTH = 128;
-    private static final int LOW_BMP_HEIGHT = 128;
+    private static final int LOW_BMP_WIDTH = 112;
+    private static final int LOW_BMP_HEIGHT = 112;
     private static final int HIGH_BMP_WIDTH = 3000;
     private static final int HIGH_BMP_HEIGHT = 4000;
     private static final int VERY_LOW_BMP_WIDTH = 1;
@@ -189,7 +189,7 @@
 
     /**
      * Test that for bitmaps of random dimensions, the mini bitmap is always created
-     * with either a width <= SMALL_SIDE or a height <= SMALL_SIDE
+     * with an area <= MINI_BITMAP_MAX_AREA
      */
     @Test
     public void testMiniBitmapCreation() {
@@ -203,14 +203,14 @@
             spyColorExtractor.onBitmapChanged(bitmap);
 
             assertThat(mMiniBitmapUpdatedCount).isEqualTo(1);
-            assertThat(Math.min(mMiniBitmapWidth, mMiniBitmapHeight))
-                    .isAtMost(WallpaperLocalColorExtractor.SMALL_SIDE);
+            assertThat(mMiniBitmapWidth * mMiniBitmapHeight)
+                    .isAtMost(WallpaperLocalColorExtractor.MINI_BITMAP_MAX_AREA);
         }
     }
 
     /**
-     * Test that for bitmaps with both width and height <= SMALL_SIDE,
-     * the mini bitmap is always created with both width and height <= SMALL_SIDE
+     * Test that for bitmaps with both width and height <= LOW_BMP_WIDTH,
+     * the mini bitmap is always created with an area <= MINI_BITMAP_MAX_AREA
      */
     @Test
     public void testSmallMiniBitmapCreation() {
@@ -224,8 +224,8 @@
             spyColorExtractor.onBitmapChanged(bitmap);
 
             assertThat(mMiniBitmapUpdatedCount).isEqualTo(1);
-            assertThat(Math.max(mMiniBitmapWidth, mMiniBitmapHeight))
-                    .isAtMost(WallpaperLocalColorExtractor.SMALL_SIDE);
+            assertThat(mMiniBitmapWidth * mMiniBitmapHeight)
+                    .isAtMost(WallpaperLocalColorExtractor.MINI_BITMAP_MAX_AREA);
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
index f8b096a..7d89a55 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/data/repository/WallpaperRepositoryImplTest.kt
@@ -33,6 +33,7 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -41,13 +42,15 @@
 @OptIn(ExperimentalCoroutinesApi::class)
 class WallpaperRepositoryImplTest : SysuiTestCase() {
 
-    private val testScope = TestScope(StandardTestDispatcher())
+    private val testDispatcher = StandardTestDispatcher()
+    private val testScope = TestScope(testDispatcher)
     private val userRepository = FakeUserRepository()
     private val wallpaperManager: WallpaperManager = mock()
 
     private val underTest: WallpaperRepositoryImpl by lazy {
         WallpaperRepositoryImpl(
             testScope.backgroundScope,
+            testDispatcher,
             fakeBroadcastDispatcher,
             userRepository,
             wallpaperManager,
@@ -102,8 +105,10 @@
             userRepository.setUserInfos(listOf(USER_WITH_SUPPORTED_WP))
             userRepository.setSelectedUserInfo(USER_WITH_SUPPORTED_WP)
 
-            // WHEN the repo initially starts up (underTest is lazy), then it fetches the current
-            // value for the wallpaper
+            // Start up the repo and let it run the initial fetch
+            underTest.wallpaperInfo
+            runCurrent()
+
             assertThat(underTest.wallpaperInfo.value).isEqualTo(SUPPORTED_WP)
         }
 
@@ -282,6 +287,10 @@
             userRepository.setUserInfos(listOf(USER_WITH_SUPPORTED_WP))
             userRepository.setSelectedUserInfo(USER_WITH_SUPPORTED_WP)
 
+            // Start up the repo and let it run the initial fetch
+            underTest.wallpaperSupportsAmbientMode
+            runCurrent()
+
             // WHEN the repo initially starts up (underTest is lazy), then it fetches the current
             // value for the wallpaper
             assertThat(underTest.wallpaperSupportsAmbientMode.value).isTrue()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index d9a0c4b..db998f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -30,6 +30,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -50,8 +52,6 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
-import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
-
 import android.app.ActivityManager;
 import android.app.IActivityManager;
 import android.app.INotificationManager;
@@ -207,6 +207,8 @@
 import com.android.wm.shell.taskview.TaskViewTransitions;
 import com.android.wm.shell.transition.Transitions;
 
+import kotlinx.coroutines.test.TestScope;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -225,8 +227,6 @@
 import java.util.Optional;
 import java.util.concurrent.Executor;
 
-import kotlinx.coroutines.test.TestScope;
-
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
diff --git a/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt b/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt
index 34c0a79..21dea6b 100644
--- a/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt
@@ -19,5 +19,5 @@
 import android.content.applicationContext
 import com.android.systemui.kosmos.Kosmos
 
-val Kosmos.layoutInflater: LayoutInflater by
+var Kosmos.layoutInflater: LayoutInflater by
     Kosmos.Fixture { LayoutInflater.from(applicationContext) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/FpsUnlockTrackerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/FpsUnlockTrackerKosmos.kt
new file mode 100644
index 0000000..6085a1f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/FpsUnlockTrackerKosmos.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
+
+val Kosmos.fpsUnlockTracker by Kosmos.Fixture { mock<FpsUnlockTracker>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderKosmos.kt
new file mode 100644
index 0000000..8281984
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderKosmos.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.ui.binder
+
+import android.content.applicationContext
+import android.view.layoutInflater
+import android.view.windowManager
+import com.android.systemui.biometrics.domain.interactor.biometricStatusInteractor
+import com.android.systemui.biometrics.domain.interactor.displayStateInteractor
+import com.android.systemui.biometrics.domain.interactor.sideFpsSensorInteractor
+import com.android.systemui.biometrics.fpsUnlockTracker
+import com.android.systemui.keyguard.domain.interactor.deviceEntrySideFpsOverlayInteractor
+import com.android.systemui.keyguard.ui.viewmodel.sideFpsProgressBarViewModel
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.kosmos.applicationCoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@OptIn(ExperimentalCoroutinesApi::class)
+val Kosmos.sideFpsOverlayViewBinder by Fixture {
+    SideFpsOverlayViewBinder(
+        applicationScope = applicationCoroutineScope,
+        applicationContext = applicationContext,
+        { biometricStatusInteractor },
+        { displayStateInteractor },
+        { deviceEntrySideFpsOverlayInteractor },
+        { fpsUnlockTracker },
+        { layoutInflater },
+        { sideFpsProgressBarViewModel },
+        { sideFpsSensorInteractor },
+        { windowManager }
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelKosmos.kt
new file mode 100644
index 0000000..de03855
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelKosmos.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.biometrics.ui.viewmodel
+
+import android.content.applicationContext
+import com.android.systemui.biometrics.domain.interactor.displayStateInteractor
+import com.android.systemui.biometrics.domain.interactor.sideFpsSensorInteractor
+import com.android.systemui.keyguard.domain.interactor.deviceEntrySideFpsOverlayInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@OptIn(ExperimentalCoroutinesApi::class)
+val Kosmos.sideFpsOverlayViewModel by Fixture {
+    SideFpsOverlayViewModel(
+        applicationContext = applicationContext,
+        deviceEntrySideFpsOverlayInteractor = deviceEntrySideFpsOverlayInteractor,
+        displayStateInteractor = displayStateInteractor,
+        sfpsSensorInteractor = sideFpsSensorInteractor,
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt
index 4a02f6d..4394847 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorKosmos.kt
@@ -26,7 +26,7 @@
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.log.sessionTracker
 import com.android.systemui.power.domain.interactor.powerInteractor
-import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.domain.interactor.sceneBackInteractor
 
 val Kosmos.bouncerInteractor by Fixture {
     BouncerInteractor(
@@ -38,6 +38,6 @@
         powerInteractor = powerInteractor,
         uiEventLogger = uiEventLogger,
         sessionTracker = sessionTracker,
-        sceneInteractor = sceneInteractor,
+        sceneBackInteractor = sceneBackInteractor,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorKosmos.kt
new file mode 100644
index 0000000..4ccee6f
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorKosmos.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import android.content.applicationContext
+import com.android.keyguard.keyguardUpdateMonitor
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
+import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+
+val Kosmos.deviceEntrySideFpsOverlayInteractor: DeviceEntrySideFpsOverlayInteractor by
+    Kosmos.Fixture {
+        DeviceEntrySideFpsOverlayInteractor(
+            applicationScope = testScope.backgroundScope,
+            context = applicationContext,
+            deviceEntryFingerprintAuthRepository = deviceEntryFingerprintAuthRepository,
+            sceneInteractor = sceneInteractor,
+            primaryBouncerInteractor = primaryBouncerInteractor,
+            alternateBouncerInteractor = alternateBouncerInteractor,
+            keyguardUpdateMonitor = keyguardUpdateMonitor
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
index 91057b6..bbe37c1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
@@ -16,14 +16,12 @@
 
 package com.android.systemui.keyguard.domain.interactor
 
-import com.android.internal.widget.lockPatternUtils
 import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.power.domain.interactor.powerInteractor
 import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
-import com.android.systemui.user.domain.interactor.selectedUserInteractor
 
 val Kosmos.fromAodTransitionInteractor by
     Kosmos.Fixture {
@@ -36,7 +34,5 @@
             keyguardInteractor = keyguardInteractor,
             powerInteractor = powerInteractor,
             keyguardOcclusionInteractor = keyguardOcclusionInteractor,
-            selectedUserInteractor = selectedUserInteractor,
-            lockPatternUtils = lockPatternUtils,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelKosmos.kt
new file mode 100644
index 0000000..8da16fc
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelKosmos.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import android.content.applicationContext
+import com.android.systemui.biometrics.domain.interactor.biometricStatusInteractor
+import com.android.systemui.biometrics.domain.interactor.displayStateInteractor
+import com.android.systemui.biometrics.domain.interactor.sideFpsSensorInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryFingerprintAuthInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.statusbar.phone.dozeServiceHost
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.sideFpsProgressBarViewModel by
+    Kosmos.Fixture {
+        SideFpsProgressBarViewModel(
+            context = applicationContext,
+            biometricStatusInteractor = biometricStatusInteractor,
+            deviceEntryFingerprintAuthInteractor = deviceEntryFingerprintAuthInteractor,
+            sfpsSensorInteractor = sideFpsSensorInteractor,
+            dozeServiceHost = dozeServiceHost,
+            keyguardInteractor = keyguardInteractor,
+            displayStateInteractor = displayStateInteractor,
+            mainDispatcher = testDispatcher,
+            applicationScope = testScope.backgroundScope,
+            powerInteractor = powerInteractor
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt
index 7dab5c2..690bde7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/data/repository/MediaFilterRepositoryKosmos.kt
@@ -16,7 +16,16 @@
 
 package com.android.systemui.media.controls.data.repository
 
+import android.content.applicationContext
 import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.policy.configurationController
 import com.android.systemui.util.time.systemClock
 
-val Kosmos.mediaFilterRepository by Kosmos.Fixture { MediaFilterRepository(systemClock) }
+val Kosmos.mediaFilterRepository by
+    Kosmos.Fixture {
+        MediaFilterRepository(
+            applicationContext = applicationContext,
+            systemClock = systemClock,
+            configurationController = configurationController
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt
index 6eae28f..069995a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaCarouselViewModelKosmos.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.media.controls.ui.viewmodel
 
 import android.content.applicationContext
+import com.android.systemui.concurrency.fakeExecutor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.kosmos.testDispatcher
@@ -32,6 +33,7 @@
             applicationScope = applicationCoroutineScope,
             applicationContext = applicationContext,
             backgroundDispatcher = testDispatcher,
+            backgroundExecutor = fakeExecutor,
             visualStabilityProvider = visualStabilityProvider,
             interactor = mediaCarouselInteractor,
             controlInteractorFactory = mediaControlInteractorFactory,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt
index b3fb15f..2f3d3c3 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/media/controls/ui/viewmodel/MediaControlViewModelKosmos.kt
@@ -17,8 +17,8 @@
 package com.android.systemui.media.controls.ui.viewmodel
 
 import android.content.applicationContext
+import com.android.systemui.concurrency.fakeExecutor
 import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.kosmos.testDispatcher
 import com.android.systemui.media.controls.domain.pipeline.interactor.mediaControlInteractor
 import com.android.systemui.media.controls.util.mediaUiEventLogger
@@ -26,9 +26,9 @@
 val Kosmos.mediaControlViewModel by
     Kosmos.Fixture {
         MediaControlViewModel(
-            applicationScope = applicationCoroutineScope,
             applicationContext = applicationContext,
             backgroundDispatcher = testDispatcher,
+            backgroundExecutor = fakeExecutor,
             interactor = mediaControlInteractor,
             logger = mediaUiEventLogger,
         )
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
index 7f6a7bd..16d08dd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneKosmos.kt
@@ -32,4 +32,15 @@
 val Kosmos.scenes by Fixture { fakeScenes }
 
 val Kosmos.initialSceneKey by Fixture { Scenes.Lockscreen }
-val Kosmos.sceneContainerConfig by Fixture { SceneContainerConfig(sceneKeys, initialSceneKey) }
+val Kosmos.sceneContainerConfig by Fixture {
+    val navigationDistances =
+        mapOf(
+            Scenes.Gone to 0,
+            Scenes.Lockscreen to 0,
+            Scenes.Communal to 1,
+            Scenes.Shade to 2,
+            Scenes.QuickSettings to 3,
+            Scenes.Bouncer to 4,
+        )
+    SceneContainerConfig(sceneKeys, initialSceneKey, navigationDistances)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorKosmos.kt
new file mode 100644
index 0000000..e46ede6
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneBackInteractorKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.scene.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.scene.sceneContainerConfig
+import com.android.systemui.scene.shared.logger.sceneLogger
+
+val Kosmos.sceneBackInteractor by Fixture {
+    SceneBackInteractor(
+        logger = sceneLogger,
+        sceneContainerConfig = sceneContainerConfig,
+    )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
index c7cf934..c0f5039 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
@@ -39,7 +39,6 @@
 import com.android.systemui.statusbar.notificationShadeWindowController
 import com.android.systemui.statusbar.phone.centralSurfaces
 import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
-import dagger.Lazy
 
 val Kosmos.sceneContainerStartable by Fixture {
     SceneContainerStartable(
@@ -55,8 +54,8 @@
         falsingCollector = falsingCollector,
         falsingManager = falsingManager,
         powerInteractor = powerInteractor,
-        simBouncerInteractor = Lazy { simBouncerInteractor },
-        authenticationInteractor = Lazy { authenticationInteractor },
+        simBouncerInteractor = { simBouncerInteractor },
+        authenticationInteractor = { authenticationInteractor },
         windowController = notificationShadeWindowController,
         deviceProvisioningInteractor = deviceProvisioningInteractor,
         centralSurfaces = centralSurfaces,
@@ -65,5 +64,6 @@
         faceUnlockInteractor = deviceEntryFaceAuthInteractor,
         shadeInteractor = shadeInteractor,
         uiEventLogger = uiEventLogger,
+        sceneBackInteractor = sceneBackInteractor,
     )
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/screenshot/scroll/FakeSession.java b/packages/SystemUI/tests/utils/src/com/android/systemui/screenshot/scroll/FakeSession.java
index 3b7b158..502e0de 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/screenshot/scroll/FakeSession.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/screenshot/scroll/FakeSession.java
@@ -32,8 +32,6 @@
 import android.media.Image;
 import android.util.Log;
 
-import com.android.systemui.screenshot.scroll.ScrollCaptureClient;
-
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
index a47b2e8..d17dd6c 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeTestUtil.kt
@@ -31,6 +31,16 @@
 /** Sets up shade state for tests for either value of the scene container flag. */
 class ShadeTestUtil constructor(val delegate: ShadeTestUtilDelegate) {
 
+    /** Sets shade expansion to a value between 0-1. */
+    fun setShadeExpansion(shadeExpansion: Float) {
+        setShadeAndQsExpansion(shadeExpansion, 0f)
+    }
+
+    /** Sets QS expansion to a value between 0-1. */
+    fun setQsExpansion(qsExpansion: Float) {
+        setShadeAndQsExpansion(0f, qsExpansion)
+    }
+
     /** Sets both shade and QS expansion. One value must be zero or values must add up to 1f. */
     fun setShadeAndQsExpansion(shadeExpansion: Float, qsExpansion: Float) {
         Assert.assertTrue(
@@ -40,15 +50,24 @@
         delegate.assertFlagValid()
         delegate.setShadeAndQsExpansionInternal(shadeExpansion, qsExpansion)
     }
+
+    /** Sets the shade expansion on the lockscreen to the given amount from 0-1. */
+    fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float) {
+        delegate.assertFlagValid()
+        delegate.setLockscreenShadeExpansion(lockscreenShadeExpansion)
+    }
 }
 
 /** Sets up shade state for tests for a specific value of the scene container flag. */
 interface ShadeTestUtilDelegate {
+    /** Asserts that the scene container flag matches this implementation. */
+    fun assertFlagValid()
+
     /** Sets both shade and QS expansion. One value must be zero or values must add up to 1f. */
     fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float)
 
-    /** Asserts that the scene container flag matches this implementation. */
-    fun assertFlagValid()
+    /** Sets the shade expansion on the lockscreen to the given amount from 0-1. */
+    fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float)
 }
 
 /** Sets up shade state for tests when the scene container flag is disabled. */
@@ -60,12 +79,16 @@
         testScope.runCurrent()
     }
 
+    override fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float) {
+        shadeRepository.setLockscreenShadeExpansion(lockscreenShadeExpansion)
+    }
+
     override fun assertFlagValid() {
         Assert.assertFalse(SceneContainerFlag.isEnabled)
     }
 }
 
-/** Sets up shade state for tests when the scene container flag is disabled. */
+/** Sets up shade state for tests when the scene container flag is enabled. */
 class ShadeTestUtilSceneImpl(val testScope: TestScope, val sceneInteractor: SceneInteractor) :
     ShadeTestUtilDelegate {
     override fun setShadeAndQsExpansionInternal(shadeExpansion: Float, qsExpansion: Float) {
@@ -78,6 +101,24 @@
         }
     }
 
+    override fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float) {
+        if (lockscreenShadeExpansion == 0f) {
+            setIdleScene(Scenes.Lockscreen)
+        } else if (lockscreenShadeExpansion == 1f) {
+            setIdleScene(Scenes.Shade)
+        } else {
+            setTransitionProgress(Scenes.Lockscreen, Scenes.Shade, lockscreenShadeExpansion)
+        }
+    }
+
+    private fun setIdleScene(scene: SceneKey) {
+        sceneInteractor.changeScene(scene, "test")
+        val transitionState =
+            MutableStateFlow<ObservableTransitionState>(ObservableTransitionState.Idle(scene))
+        sceneInteractor.setTransitionState(transitionState)
+        testScope.runCurrent()
+    }
+
     private fun setTransitionProgress(from: SceneKey, to: SceneKey, progress: Float) {
         sceneInteractor.changeScene(from, "test")
         val transitionState =
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/smartspace/viewmodel/SmartspaceViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/smartspace/viewmodel/SmartspaceViewModelKosmos.kt
new file mode 100644
index 0000000..ebaf323
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/smartspace/viewmodel/SmartspaceViewModelKosmos.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.smartspace.viewmodel
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.smartspace.ui.viewmodel.SmartspaceViewModel
+
+val Kosmos.smartspaceViewModelFactory by
+    Kosmos.Fixture {
+        object : SmartspaceViewModel.Factory {
+            override fun create(surfaceName: String): SmartspaceViewModel {
+                return SmartspaceViewModel(
+                    powerInteractor = powerInteractor,
+                    surfaceName = surfaceName
+                )
+            }
+        }
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
index b91f7e6..2bd584e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/NotificationEntryBuilder.java
@@ -33,10 +33,10 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection;
 import com.android.systemui.util.time.FakeSystemClock;
 
-import java.util.ArrayList;
-
 import kotlin.Unit;
 
+import java.util.ArrayList;
+
 /**
  * Combined builder for constructing a NotificationEntry and its associated StatusBarNotification
  * and Ranking. Is largely a proxy for the SBN and Ranking builders, but does a little extra magic
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
index 3774d1d..a8328e4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -17,9 +17,9 @@
 import android.testing.LeakCheck;
 
 import com.android.internal.statusbar.StatusBarIcon;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState;
+import com.android.systemui.statusbar.phone.ui.IconManager;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 
 import java.util.List;
 
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/LeakCheckedTest.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
index ec1f352..5d21ddd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
@@ -21,7 +21,7 @@
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.ui.StatusBarIconController;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 8905ad3..3337419 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -163,6 +163,8 @@
     test_suites: ["general-tests"],
     data: [
         ":framework-minus-apex.ravenwood.stats",
+        ":framework-minus-apex.ravenwood.apis",
         ":services.core.ravenwood.stats",
+        ":services.core.ravenwood.apis",
     ],
 }
diff --git a/ravenwood/scripts/ravenwood-stats-collector.sh b/ravenwood/scripts/ravenwood-stats-collector.sh
index 4dcaa2b..b5843d0 100755
--- a/ravenwood/scripts/ravenwood-stats-collector.sh
+++ b/ravenwood/scripts/ravenwood-stats-collector.sh
@@ -17,8 +17,9 @@
 
 set -e
 
-# Output file
-out=/tmp/ravenwood-stats-all.csv
+# Output files
+stats=/tmp/ravenwood-stats-all.csv
+apis=/tmp/ravenwood-apis-all.csv
 
 # Where the input files are.
 path=$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/ravenwood-stats-checker/x86_64/
@@ -41,12 +42,28 @@
     sed -e '1d' -e "s/^/$jar,/"  $file
 }
 
-collect() {
-    echo 'Jar,PackageName,ClassName,SupportedMethods,TotalMethods'
-    dump "framework-minus-apex"  hoststubgen_framework-minus-apex_stats.csv
-    dump "service.core"  hoststubgen_services.core_stats.csv
+collect_stats() {
+    local out="$1"
+    {
+        echo 'Jar,PackageName,ClassName,SupportedMethods,TotalMethods'
+        dump "framework-minus-apex"  hoststubgen_framework-minus-apex_stats.csv
+        dump "service.core"  hoststubgen_services.core_stats.csv
+    } > "$out"
+
+    echo "Stats CVS created at $out"
 }
 
-collect >$out
+collect_apis() {
+    local out="$1"
+    {
+        echo 'Jar,PackageName,ClassName,MethodName,Descriptor'
+        dump "framework-minus-apex"  hoststubgen_framework-minus-apex_apis.csv
+        dump "service.core"  hoststubgen_services.core_apis.csv
+    } > "$out"
 
-echo "Full dump CVS created at $out"
+    echo "API CVS created at $out"
+}
+
+
+collect_stats $stats
+collect_apis $apis
diff --git a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
index 697ef87..91ba9b3 100644
--- a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
@@ -56,6 +56,7 @@
     @GuardedBy("mTransports")
     private final SparseArray<Transport> mTransports = new SparseArray<>();
     @NonNull
+    @GuardedBy("mTransportsListeners")
     private final RemoteCallbackList<IOnTransportsChangedListener> mTransportsListeners =
             new RemoteCallbackList<>();
     /** Message type -> IOnMessageReceivedListener */
@@ -84,34 +85,28 @@
      */
     public void addListener(IOnTransportsChangedListener listener) {
         Slog.i(TAG, "Registering OnTransportsChangedListener");
-        mTransportsListeners.register(listener);
-        List<AssociationInfo> associations = new ArrayList<>();
-        synchronized (mTransports) {
-            for (int i = 0; i < mTransports.size(); i++) {
-                AssociationInfo association = mAssociationStore.getAssociationById(
-                        mTransports.keyAt(i));
-                if (association != null) {
-                    associations.add(association);
+        synchronized (mTransportsListeners) {
+            mTransportsListeners.register(listener);
+            mTransportsListeners.broadcast(listener1 -> {
+                // callback to the current listener with all the associations of the transports
+                // immediately
+                if (listener1 == listener) {
+                    try {
+                        listener.onTransportsChanged(getAssociationsWithTransport());
+                    } catch (RemoteException ignored) {
+                    }
                 }
-            }
+            });
         }
-        mTransportsListeners.broadcast(listener1 -> {
-            // callback to the current listener with all the associations of the transports
-            // immediately
-            if (listener1 == listener) {
-                try {
-                    listener.onTransportsChanged(associations);
-                } catch (RemoteException ignored) {
-                }
-            }
-        });
     }
 
     /**
      * Remove the listener for receiving callbacks when any of the transports is changed
      */
     public void removeListener(IOnTransportsChangedListener listener) {
-        mTransportsListeners.unregister(listener);
+        synchronized (mTransportsListeners) {
+            mTransportsListeners.unregister(listener);
+        }
     }
 
     /**
@@ -179,7 +174,7 @@
         Slog.i(TAG, "Transport detached.");
     }
 
-    private void notifyOnTransportsChanged() {
+    private List<AssociationInfo> getAssociationsWithTransport() {
         List<AssociationInfo> associations = new ArrayList<>();
         synchronized (mTransports) {
             for (int i = 0; i < mTransports.size(); i++) {
@@ -190,12 +185,18 @@
                 }
             }
         }
-        mTransportsListeners.broadcast(listener -> {
-            try {
-                listener.onTransportsChanged(associations);
-            } catch (RemoteException ignored) {
-            }
-        });
+        return associations;
+    }
+
+    private void notifyOnTransportsChanged() {
+        synchronized (mTransportsListeners) {
+            mTransportsListeners.broadcast(listener -> {
+                try {
+                    listener.onTransportsChanged(getAssociationsWithTransport());
+                } catch (RemoteException ignored) {
+                }
+            });
+        }
     }
 
     private void initializeTransport(int associationId,
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index eec22c9..a6b7809 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2425,7 +2425,7 @@
                                 final long before24Hr = Math.max(0,
                                             SystemClock.elapsedRealtime() - (24 * 60 * 60 * 1000));
                                 final long lastTimeOutAt = fgsTypeInfo.getTimeLimitExceededAt();
-                                if (fgsTypeInfo.getFirstFgsStartTime() < before24Hr
+                                if (fgsTypeInfo.getFirstFgsStartRealtime() < before24Hr
                                         || (lastTimeOutAt != Long.MIN_VALUE
                                             && r.app.mState.getLastTopTime() > lastTimeOutAt)) {
                                     // Reset the time limit info for this fgs type if it has been
@@ -3724,6 +3724,33 @@
         return fgsType;
     }
 
+    /**
+     * @return the constant time limit defined for the given foreground service type.
+     */
+    private long getTimeLimitForFgsType(int foregroundServiceType) {
+        return switch (foregroundServiceType) {
+            case ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING ->
+                    mAm.mConstants.mMediaProcessingFgsTimeoutDuration;
+            case ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC ->
+                    mAm.mConstants.mDataSyncFgsTimeoutDuration;
+            // Add logic for time limits introduced in the future for other fgs types above.
+            default -> Long.MAX_VALUE;
+        };
+    }
+
+    /**
+     * @return the next stop time for the given type, based on how long it has already ran for.
+     * The total runtime is automatically reset 24hrs after the first fgs start of this type
+     * or if the app has recently been in the TOP state when the app calls startForeground().
+     */
+    private long getNextFgsStopTime(int fgsType, TimeLimitedFgsInfo fgsInfo) {
+        final long timeLimit = getTimeLimitForFgsType(fgsType);
+        if (timeLimit == Long.MAX_VALUE) {
+            return Long.MAX_VALUE;
+        }
+        return fgsInfo.getLastFgsStartTime() + Math.max(0, timeLimit - fgsInfo.getTotalRuntime());
+    }
+
     private void maybeUpdateFgsTrackingLocked(ServiceRecord sr, int previousFgsType) {
         final int previouslyTimeLimitedType = getTimeLimitedFgsType(previousFgsType);
         if (previouslyTimeLimitedType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE
@@ -3755,7 +3782,7 @@
         }
 
         traceInstant("FGS start: ", sr);
-        final long nowRealtime = SystemClock.elapsedRealtime();
+        final long nowUptime = SystemClock.uptimeMillis();
 
         // Fetch/create/update the fgs info for the time-limited type.
         SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(sr.appInfo.uid);
@@ -3766,10 +3793,10 @@
         final int timeLimitedFgsType = getTimeLimitedFgsType(sr.foregroundServiceType);
         TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(timeLimitedFgsType);
         if (fgsTypeInfo == null) {
-            fgsTypeInfo = sr.createTimeLimitedFgsInfo(nowRealtime);
+            fgsTypeInfo = sr.createTimeLimitedFgsInfo(nowUptime);
             fgsInfo.put(timeLimitedFgsType, fgsTypeInfo);
         }
-        fgsTypeInfo.setLastFgsStartTime(nowRealtime);
+        fgsTypeInfo.setLastFgsStartTime(nowUptime);
 
         // We'll cancel the previous ANR timer and start a fresh one below.
         mFGSAnrTimer.cancel(sr);
@@ -3777,7 +3804,7 @@
 
         final Message msg = mAm.mHandler.obtainMessage(
                 ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
-        final long timeoutCallbackTime = sr.getNextFgsStopTime(timeLimitedFgsType, fgsTypeInfo);
+        final long timeoutCallbackTime = getNextFgsStopTime(timeLimitedFgsType, fgsTypeInfo);
         if (timeoutCallbackTime == Long.MAX_VALUE) {
             // This should never happen since we only get to this point if the service record's
             // foregroundServiceType attribute contains a type that can be timed-out.
@@ -3829,10 +3856,24 @@
     void onFgsTimeout(ServiceRecord sr) {
         synchronized (mAm) {
             final int fgsType = getTimeLimitedFgsType(sr.foregroundServiceType);
-            if (fgsType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE) {
+            if (fgsType == ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE || sr.app == null) {
                 mFGSAnrTimer.discard(sr);
                 return;
             }
+
+            final long lastTopTime = sr.app.mState.getLastTopTime();
+            final long constantTimeLimit = getTimeLimitForFgsType(fgsType);
+            final long nowUptime = SystemClock.uptimeMillis();
+            if (constantTimeLimit > (nowUptime - lastTopTime)) {
+                // The app was in the TOP state after the FGS was started so its time allowance
+                // should be counted from that time since this is considered a user interaction
+                mFGSAnrTimer.discard(sr);
+                final Message msg = mAm.mHandler.obtainMessage(
+                                        ActivityManagerService.SERVICE_FGS_TIMEOUT_MSG, sr);
+                mAm.mHandler.sendMessageAtTime(msg, lastTopTime + constantTimeLimit);
+                return;
+            }
+
             Slog.e(TAG_SERVICE, "FGS (" + ServiceInfo.foregroundServiceTypeToLabel(fgsType)
                     + ") timed out: " + sr);
             mFGSAnrTimer.accept(sr);
@@ -3843,14 +3884,13 @@
                 final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(fgsType);
                 if (fgsTypeInfo != null) {
                     // Update total runtime for the time-limited fgs type and mark it as timed out.
-                    final long nowRealtime = SystemClock.elapsedRealtime();
                     fgsTypeInfo.updateTotalRuntime();
-                    fgsTypeInfo.setTimeLimitExceededAt(nowRealtime);
+                    fgsTypeInfo.setTimeLimitExceededAt(nowUptime);
 
                     logFGSStateChangeLocked(sr,
                             FOREGROUND_SERVICE_STATE_CHANGED__STATE__TIMED_OUT,
-                            nowRealtime > fgsTypeInfo.getLastFgsStartTime()
-                                    ? (int) (nowRealtime - fgsTypeInfo.getLastFgsStartTime()) : 0,
+                            nowUptime > fgsTypeInfo.getLastFgsStartTime()
+                                    ? (int) (nowUptime - fgsTypeInfo.getLastFgsStartTime()) : 0,
                             FGS_STOP_REASON_UNKNOWN,
                             FGS_TYPE_POLICY_CHECK_UNKNOWN,
                             FOREGROUND_SERVICE_STATE_CHANGED__FGS_START_API__FGSSTARTAPI_NA,
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index f7ed702..9e06b75 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -2473,6 +2473,9 @@
         pw.print("  "); pw.print(KEY_PSS_TO_RSS_THRESHOLD_MODIFIER);
         pw.print("="); pw.println(PSS_TO_RSS_THRESHOLD_MODIFIER);
 
+        pw.print("  "); pw.print(KEY_MAX_PREVIOUS_TIME);
+        pw.print("="); pw.println(MAX_PREVIOUS_TIME);
+
         pw.println();
         if (mOverrideMaxCachedProcesses >= 0) {
             pw.print("  mOverrideMaxCachedProcesses="); pw.println(mOverrideMaxCachedProcesses);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cf09cfb..c47e42d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3541,13 +3541,23 @@
                 mAppProfiler.setAllowLowerMemLevelLocked(false);
                 doLowMem = false;
             }
+            if (doOomAdj) {
+                if (Flags.migrateFullOomadjUpdates()) {
+                    app.forEachConnectionHost((host) -> enqueueOomAdjTargetLocked(host));
+                }
+            }
+
             EventLogTags.writeAmProcDied(app.userId, pid, app.processName, setAdj, setProcState);
             if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
                 "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
             handleAppDiedLocked(app, pid, false, true, fromBinderDied);
 
             if (doOomAdj) {
-                updateOomAdjLocked(OOM_ADJ_REASON_PROCESS_END);
+                if (Flags.migrateFullOomadjUpdates()) {
+                    updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_PROCESS_END);
+                } else {
+                    updateOomAdjLocked(OOM_ADJ_REASON_PROCESS_END);
+                }
             }
             if (doLowMem) {
                 mAppProfiler.doLowMemReportIfNeededLocked(app);
@@ -4436,8 +4446,17 @@
                         packageName, null, userId);
         }
 
-        final boolean clearPendingIntentsForStoppedApp = (android.content.pm.Flags.stayStopped()
-                && packageStateStopped);
+        boolean clearPendingIntentsForStoppedApp = false;
+        try {
+            clearPendingIntentsForStoppedApp = (packageStateStopped
+                    && android.content.pm.Flags.stayStopped());
+        } catch (IllegalStateException e) {
+            // It's unlikely for a package to be force-stopped early in the boot cycle. So, if we
+            // check for 'packageStateStopped' which should evaluate to 'false', then this should
+            // ensure we are not accessing the flag early in the boot cycle. As an additional
+            // safety measure, catch the exception and ignore to avoid causing a device restart.
+            clearPendingIntentsForStoppedApp = false;
+        }
         if (packageName == null || uninstalling || clearPendingIntentsForStoppedApp) {
             final int cancelReason;
             if (packageName == null) {
@@ -17714,11 +17733,6 @@
     }
 
     @GuardedBy({"this", "mProcLock"})
-    final void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
-        mOomAdjuster.setAppIdTempAllowlistStateLSP(uid, onAllowlist);
-    }
-
-    @GuardedBy({"this", "mProcLock"})
     final void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) {
         mOomAdjuster.setUidTempAllowlistStateLSP(uid, onAllowlist);
     }
@@ -18680,7 +18694,7 @@
                     } else {
                         mFgsStartTempAllowList.removeUid(changingUid);
                     }
-                    setAppIdTempAllowlistStateLSP(changingUid, adding);
+                    setUidTempAllowlistStateLSP(changingUid, adding);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index bf4f34f..5af9424 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -117,6 +117,7 @@
 import android.util.DisplayMetrics;
 import android.util.TeeWriter;
 import android.util.proto.ProtoOutputStream;
+import android.view.Choreographer;
 import android.view.Display;
 import android.window.SplashScreen;
 
@@ -241,6 +242,23 @@
                 case "start":
                 case "start-activity":
                     return runStartActivity(pw);
+                case "start-in-vsync":
+                    final ProgressWaiter waiter = new ProgressWaiter(0);
+                    final int[] startResult = new int[1];
+                    startResult[0] = -1;
+                    mInternal.mUiHandler.runWithScissors(
+                            () -> Choreographer.getInstance().postFrameCallback(frameTimeNanos -> {
+                                try {
+                                    startResult[0] = runStartActivity(pw);
+                                    waiter.onFinished(0, null /* extras */);
+                                } catch (Exception ex) {
+                                    getErrPrintWriter().println(
+                                            "Error: unable to start activity, " + ex);
+                                }
+                            }),
+                            USER_OPERATION_TIMEOUT_MS / 2);
+                    waiter.waitForFinish(USER_OPERATION_TIMEOUT_MS);
+                    return startResult[0];
                 case "startservice":
                 case "start-service":
                     return runStartService(pw, false);
@@ -281,6 +299,8 @@
                     return runClearWatchHeap(pw);
                 case "clear-start-info":
                     return runClearStartInfo(pw);
+                case "start-info-detailed-monitoring":
+                    return runStartInfoDetailedMonitoring(pw);
                 case "clear-exit-info":
                     return runClearExitInfo(pw);
                 case "bug-report":
@@ -1395,12 +1415,12 @@
                 "runClearStartInfo()");
         String opt;
         int userId = UserHandle.USER_CURRENT;
-        String packageName = null;
         while ((opt = getNextOption()) != null) {
             if (opt.equals("--user")) {
                 userId = UserHandle.parseUserArg(getNextArgRequired());
             } else {
-                packageName = opt;
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
             }
         }
         if (userId == UserHandle.USER_CURRENT) {
@@ -1411,21 +1431,19 @@
             userId = user.id;
         }
         mInternal.mProcessList.getAppStartInfoTracker()
-                .clearHistoryProcessStartInfo(packageName, userId);
+                .clearHistoryProcessStartInfo(getNextArg(), userId);
         return 0;
     }
 
-    int runClearExitInfo(PrintWriter pw) throws RemoteException {
-        mInternal.enforceCallingPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
-                "runClearExitInfo()");
+    int runStartInfoDetailedMonitoring(PrintWriter pw) throws RemoteException {
         String opt;
         int userId = UserHandle.USER_CURRENT;
-        String packageName = null;
         while ((opt = getNextOption()) != null) {
             if (opt.equals("--user")) {
                 userId = UserHandle.parseUserArg(getNextArgRequired());
             } else {
-                packageName = opt;
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
             }
         }
         if (userId == UserHandle.USER_CURRENT) {
@@ -1435,7 +1453,33 @@
             }
             userId = user.id;
         }
-        mInternal.mProcessList.mAppExitInfoTracker.clearHistoryProcessExitInfo(packageName, userId);
+        mInternal.mProcessList.getAppStartInfoTracker()
+                .configureDetailedMonitoring(pw, getNextArg(), userId);
+        return 0;
+    }
+
+    int runClearExitInfo(PrintWriter pw) throws RemoteException {
+        mInternal.enforceCallingPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS,
+                "runClearExitInfo()");
+        String opt;
+        int userId = UserHandle.USER_CURRENT;
+        while ((opt = getNextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+        if (userId == UserHandle.USER_CURRENT) {
+            UserInfo user = mInterface.getCurrentUser();
+            if (user == null) {
+                return -1;
+            }
+            userId = user.id;
+        }
+        mInternal.mProcessList.mAppExitInfoTracker.clearHistoryProcessExitInfo(getNextArg(),
+                userId);
         return 0;
     }
 
@@ -4236,6 +4280,9 @@
             pw.println("      --activityType <ACTIVITY_TYPE>: The activity type to launch the activity as.");
             pw.println("      --display <DISPLAY_ID>: The display to launch the activity into.");
             pw.println("      --splashscreen-icon: Show the splash screen icon on launch.");
+            pw.println("  start-in-vsync");
+            pw.println("      Start an Activity with vsync aligned. See `start-activity` for the");
+            pw.println("      possible options.");
             pw.println("  start-service [--user <USER_ID> | current] <INTENT>");
             pw.println("      Start a Service.  Options are:");
             pw.println("      --user <USER_ID> | current: Specify which user to run as; if not");
@@ -4356,10 +4403,15 @@
             pw.println("      above <HEAP-LIMIT> then a heap dump is collected for the user to report.");
             pw.println("  clear-watch-heap");
             pw.println("      Clear the previously set-watch-heap.");
-            pw.println("  clear-start-info [--user <USER_ID> | all | current] [package]");
-            pw.println("      Clear the process start-info for given package");
-            pw.println("  clear-exit-info [--user <USER_ID> | all | current] [package]");
-            pw.println("      Clear the process exit-info for given package");
+            pw.println("  clear-start-info [--user <USER_ID> | all | current] <PACKAGE>");
+            pw.println("      Clear process start-info for the given package.");
+            pw.println("      Clear start-info for all packages if no package is provided.");
+            pw.println("  start-info-detailed-monitoring [--user <USER_ID> | all | current] <PACKAGE>");
+            pw.println("      Enable application start info detailed monitoring for the given package.");
+            pw.println("      Disable if no package is supplied.");
+            pw.println("  clear-exit-info [--user <USER_ID> | all | current] <PACKAGE>");
+            pw.println("      Clear process exit-info for the given package.");
+            pw.println("      Clear exit-info for all packages if no package is provided.");
             pw.println("  bug-report [--progress | --telephony]");
             pw.println("      Request bug report generation; will launch a notification");
             pw.println("        when done to select where it should be delivered. Options are:");
diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java
index 2be1fe2..376f654 100644
--- a/services/core/java/com/android/server/am/AppStartInfoTracker.java
+++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java
@@ -65,6 +65,7 @@
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -82,8 +83,12 @@
     private static final int FOREACH_ACTION_REMOVE_ITEM = 1;
     private static final int FOREACH_ACTION_STOP_ITERATION = 2;
 
+    private static final String MONITORING_MODE_EMPTY_TEXT = "No records";
+
     @VisibleForTesting static final int APP_START_INFO_HISTORY_LIST_SIZE = 16;
 
+    private static final int APP_START_INFO_MONITORING_MODE_LIST_SIZE = 100;
+
     @VisibleForTesting static final String APP_START_STORE_DIR = "procstartstore";
 
     @VisibleForTesting static final String APP_START_INFO_FILE = "procstartinfo";
@@ -426,6 +431,40 @@
                 ApplicationStartInfo.START_TIMESTAMP_APPLICATION_ONCREATE);
     }
 
+    /**
+     * Helper functions for monitoring shell command.
+     * > adb shell am start-info-detailed-monitoring [package-name]
+     */
+    void configureDetailedMonitoring(PrintWriter pw, String packageName, int userId) {
+        synchronized (mLock) {
+            if (!mEnabled) {
+                return;
+            }
+
+            forEachPackageLocked((name, records) -> {
+                for (int i = 0; i < records.size(); i++) {
+                    records.valueAt(i).disableAppMonitoringMode();
+                }
+                return AppStartInfoTracker.FOREACH_ACTION_NONE;
+            });
+
+            if (TextUtils.isEmpty(packageName)) {
+                pw.println("ActivityManager AppStartInfo detailed monitoring disabled");
+            } else {
+                SparseArray<AppStartInfoContainer> array = mData.getMap().get(packageName);
+                if (array != null) {
+                    for (int i = 0; i < array.size(); i++) {
+                        array.valueAt(i).enableAppMonitoringModeForUser(userId);
+                    }
+                    pw.println("ActivityManager AppStartInfo detailed monitoring enabled for "
+                            + packageName);
+                } else {
+                    pw.println("Package " + packageName + " not found");
+                }
+            }
+        }
+    }
+
     /** Report a bind application timestamp to add to {@link ApplicationStartInfo}. */
     public void reportBindApplicationTimeNanos(ProcessRecord app, long timeNs) {
         addTimestampToStart(app, timeNs,
@@ -1011,15 +1050,46 @@
 
     /** A container class of (@link android.app.ApplicationStartInfo) */
     final class AppStartInfoContainer {
-        private List<ApplicationStartInfo> mInfos; // Always kept sorted by first timestamp.
+        private ArrayList<ApplicationStartInfo> mInfos; // Always kept sorted by first timestamp.
         private int mMaxCapacity;
         private int mUid;
+        private boolean mMonitoringModeEnabled = false;
 
         AppStartInfoContainer(final int maxCapacity) {
             mInfos = new ArrayList<ApplicationStartInfo>();
             mMaxCapacity = maxCapacity;
         }
 
+        int getMaxCapacity() {
+            return mMonitoringModeEnabled ? APP_START_INFO_MONITORING_MODE_LIST_SIZE : mMaxCapacity;
+        }
+
+        @GuardedBy("mLock")
+        void enableAppMonitoringModeForUser(int userId) {
+            if (UserHandle.getUserId(mUid) == userId) {
+                mMonitoringModeEnabled = true;
+            }
+        }
+
+        @GuardedBy("mLock")
+        void disableAppMonitoringMode() {
+            mMonitoringModeEnabled = false;
+
+            // Capacity is reduced by turning off monitoring mode. Check if array size is within
+            // new lower limits and trim extraneous records if it is not.
+            if (mInfos.size() <= getMaxCapacity()) {
+                return;
+            }
+
+            // Sort records so we can remove the least recent ones.
+            Collections.sort(mInfos, (a, b) ->
+                    Long.compare(getStartTimestamp(b), getStartTimestamp(a)));
+
+            // Remove records and trim list object back to size.
+            mInfos.subList(0, mInfos.size() - getMaxCapacity()).clear();
+            mInfos.trimToSize();
+        }
+
         @GuardedBy("mLock")
         void getStartInfoLocked(
                 final int filterPid, final int maxNum, ArrayList<ApplicationStartInfo> results) {
@@ -1029,7 +1099,7 @@
         @GuardedBy("mLock")
         void addStartInfoLocked(ApplicationStartInfo info) {
             int size = mInfos.size();
-            if (size >= mMaxCapacity) {
+            if (size >= getMaxCapacity()) {
                 // Remove oldest record if size is over max capacity.
                 int oldestIndex = -1;
                 long oldestTimeStamp = Long.MAX_VALUE;
@@ -1061,12 +1131,59 @@
 
         @GuardedBy("mLock")
         void dumpLocked(PrintWriter pw, String prefix, SimpleDateFormat sdf) {
+            if (mMonitoringModeEnabled) {
+                // For monitoring mode, calculate the average start time for each start state to
+                // add to output.
+                List<Long> coldStartTimes = new ArrayList<>();
+                List<Long> warmStartTimes = new ArrayList<>();
+                List<Long> hotStartTimes = new ArrayList<>();
+
+                for (int i = 0; i < mInfos.size(); i++) {
+                    ApplicationStartInfo startInfo = mInfos.get(i);
+                    Map<Integer, Long> timestamps = startInfo.getStartupTimestamps();
+
+                    // Confirm required timestamps exist.
+                    if (timestamps.containsKey(ApplicationStartInfo.START_TIMESTAMP_LAUNCH)
+                            && timestamps.containsKey(
+                            ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME)) {
+                        // Add timestamp to correct collection.
+                        long time = timestamps.get(ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME)
+                                - timestamps.get(ApplicationStartInfo.START_TIMESTAMP_LAUNCH);
+                        switch (startInfo.getStartType()) {
+                            case ApplicationStartInfo.START_TYPE_COLD:
+                                coldStartTimes.add(time);
+                                break;
+                            case ApplicationStartInfo.START_TYPE_WARM:
+                                warmStartTimes.add(time);
+                                break;
+                            case ApplicationStartInfo.START_TYPE_HOT:
+                                hotStartTimes.add(time);
+                                break;
+                        }
+                    }
+                }
+
+                pw.println(prefix + "  Average Start Time in ns for Cold Starts: "
+                        + (coldStartTimes.isEmpty()  ? MONITORING_MODE_EMPTY_TEXT
+                                : calculateAverage(coldStartTimes)));
+                pw.println(prefix + "  Average Start Time in ns for Warm Starts: "
+                        + (warmStartTimes.isEmpty() ? MONITORING_MODE_EMPTY_TEXT
+                                : calculateAverage(warmStartTimes)));
+                pw.println(prefix + "  Average Start Time in ns for Hot Starts: "
+                        + (hotStartTimes.isEmpty() ? MONITORING_MODE_EMPTY_TEXT
+                                : calculateAverage(hotStartTimes)));
+            }
+
             int size = mInfos.size();
             for (int i = 0; i < size; i++) {
                 mInfos.get(i).dump(pw, prefix + "  ", "#" + i, sdf);
             }
         }
 
+        private long calculateAverage(List<Long> vals) {
+            return (long) vals.stream().mapToDouble(a -> a).average().orElse(0.0);
+        }
+
         @GuardedBy("mLock")
         void writeToProto(ProtoOutputStream proto, long fieldId) throws IOException {
             long token = proto.start(fieldId);
@@ -1076,6 +1193,7 @@
                 mInfos.get(i)
                         .writeToProto(proto, AppsStartInfoProto.Package.User.APP_START_INFO);
             }
+            proto.write(AppsStartInfoProto.Package.User.MONITORING_ENABLED, mMonitoringModeEnabled);
             proto.end(token);
         }
 
@@ -1094,6 +1212,10 @@
                         info.readFromProto(proto, AppsStartInfoProto.Package.User.APP_START_INFO);
                         mInfos.add(info);
                         break;
+                    case (int) AppsStartInfoProto.Package.User.MONITORING_ENABLED:
+                        mMonitoringModeEnabled = proto.readBoolean(
+                            AppsStartInfoProto.Package.User.MONITORING_ENABLED);
+                        break;
                 }
             }
             proto.end(token);
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 9b72db8..a289dd1 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -3696,27 +3696,18 @@
     }
 
     @GuardedBy({"mService", "mProcLock"})
-    void setAppIdTempAllowlistStateLSP(int uid, boolean onAllowlist) {
-        boolean changed = false;
-        for (int i = mActiveUids.size() - 1; i >= 0; i--) {
-            final UidRecord uidRec = mActiveUids.valueAt(i);
-            if (uidRec.getUid() == uid && uidRec.isCurAllowListed() != onAllowlist) {
-                uidRec.setCurAllowListed(onAllowlist);
-                changed = true;
-            }
-        }
-        if (changed) {
-            updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
-        }
-    }
-
-    @GuardedBy({"mService", "mProcLock"})
     void setUidTempAllowlistStateLSP(int uid, boolean onAllowlist) {
-        boolean changed = false;
         final UidRecord uidRec = mActiveUids.get(uid);
         if (uidRec != null && uidRec.isCurAllowListed() != onAllowlist) {
             uidRec.setCurAllowListed(onAllowlist);
-            updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
+            if (Flags.migrateFullOomadjUpdates()) {
+                for (int i = uidRec.getNumOfProcs() - 1; i >= 0; i--) {
+                    enqueueOomAdjTargetLocked(uidRec.getProcessRecordByIndex(i));
+                }
+                updateOomAdjPendingTargetsLocked(OOM_ADJ_REASON_ALLOWLIST);
+            } else {
+                updateOomAdjLSP(OOM_ADJ_REASON_ALLOWLIST);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 0816527..a74c489 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -71,6 +71,7 @@
 import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.List;
+import java.util.function.Consumer;
 
 /**
  * Full information about a particular process that
@@ -1692,4 +1693,22 @@
                 && !mOptRecord.shouldNotFreeze()
                 && mState.getCurAdj() >= ProcessList.FREEZER_CUTOFF_ADJ;
     }
+
+    public void forEachConnectionHost(Consumer<ProcessRecord> consumer) {
+        for (int i = mServices.numberOfConnections() - 1; i >= 0; i--) {
+            final ConnectionRecord cr = mServices.getConnectionAt(i);
+            final ProcessRecord service = cr.binding.service.app;
+            consumer.accept(service);
+        }
+        for (int i = mServices.numberOfSdkSandboxConnections() - 1; i >= 0; i--) {
+            final ConnectionRecord cr = mServices.getSdkSandboxConnectionAt(i);
+            final ProcessRecord service = cr.binding.service.app;
+            consumer.accept(service);
+        }
+        for (int i = mProviders.numberOfProviderConnections() - 1; i >= 0; i--) {
+            ContentProviderConnection cpc = mProviders.getProviderConnectionAt(i);
+            ProcessRecord provider = cpc.provider.proc;
+            consumer.accept(provider);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 065f3bd..8eca4fc 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -33,6 +33,7 @@
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UptimeMillisLong;
 import android.app.BackgroundStartPrivileges;
 import android.app.IApplicationThread;
 import android.app.Notification;
@@ -677,52 +678,65 @@
      * Data container class to help track certain fgs info for time-restricted types.
      */
     static class TimeLimitedFgsInfo {
+        @UptimeMillisLong
+        private long mFirstFgsStartUptime;
+        // The first fgs start time is maintained here separately in realtime-base
+        // for the 24-hour window reset logic.
         @ElapsedRealtimeLong
-        private long mFirstFgsStartTime;
-        @ElapsedRealtimeLong
+        private long mFirstFgsStartRealtime;
+        @UptimeMillisLong
         private long mLastFgsStartTime;
-        @ElapsedRealtimeLong
+        @UptimeMillisLong
         private long mTimeLimitExceededAt = Long.MIN_VALUE;
+        @UptimeMillisLong
         private long mTotalRuntime = 0;
 
-        TimeLimitedFgsInfo(@ElapsedRealtimeLong long startTime) {
-            mFirstFgsStartTime = startTime;
+        TimeLimitedFgsInfo(@UptimeMillisLong long startTime) {
+            mFirstFgsStartUptime = startTime;
+            mFirstFgsStartRealtime = SystemClock.elapsedRealtime();
             mLastFgsStartTime = startTime;
         }
 
-        @ElapsedRealtimeLong
-        public long getFirstFgsStartTime() {
-            return mFirstFgsStartTime;
+        @UptimeMillisLong
+        public long getFirstFgsStartUptime() {
+            return mFirstFgsStartUptime;
         }
 
-        public void setLastFgsStartTime(@ElapsedRealtimeLong long startTime) {
+        @ElapsedRealtimeLong
+        public long getFirstFgsStartRealtime() {
+            return mFirstFgsStartRealtime;
+        }
+
+        public void setLastFgsStartTime(@UptimeMillisLong long startTime) {
             mLastFgsStartTime = startTime;
         }
 
-        @ElapsedRealtimeLong
+        @UptimeMillisLong
         public long getLastFgsStartTime() {
             return mLastFgsStartTime;
         }
 
         public void updateTotalRuntime() {
-            mTotalRuntime += SystemClock.elapsedRealtime() - mLastFgsStartTime;
+            mTotalRuntime += SystemClock.uptimeMillis() - mLastFgsStartTime;
         }
 
+        @UptimeMillisLong
         public long getTotalRuntime() {
             return mTotalRuntime;
         }
 
-        public void setTimeLimitExceededAt(@ElapsedRealtimeLong long timeLimitExceededAt) {
+        public void setTimeLimitExceededAt(@UptimeMillisLong long timeLimitExceededAt) {
             mTimeLimitExceededAt = timeLimitExceededAt;
         }
 
-        @ElapsedRealtimeLong
+        @UptimeMillisLong
         public long getTimeLimitExceededAt() {
             return mTimeLimitExceededAt;
         }
 
         public void reset() {
-            mFirstFgsStartTime = 0;
+            mFirstFgsStartUptime = 0;
+            mFirstFgsStartRealtime = 0;
             mLastFgsStartTime = 0;
             mTotalRuntime = 0;
             mTimeLimitExceededAt = Long.MIN_VALUE;
@@ -1858,8 +1872,8 @@
     /**
      * Called when a time-limited FGS starts.
      */
-    public TimeLimitedFgsInfo createTimeLimitedFgsInfo(@ElapsedRealtimeLong long nowRealtime) {
-        return new TimeLimitedFgsInfo(nowRealtime);
+    public TimeLimitedFgsInfo createTimeLimitedFgsInfo(@UptimeMillisLong long nowUptime) {
+        return new TimeLimitedFgsInfo(nowUptime);
     }
 
     /**
@@ -1872,27 +1886,6 @@
                         != ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE;
     }
 
-    /**
-     * @return the next stop time for the given type, based on how long it has already ran for.
-     * The total runtime is automatically reset 24hrs after the first fgs start of this type
-     * or if the app has recently been in the TOP state when the app calls startForeground().
-     */
-    long getNextFgsStopTime(int fgsType, TimeLimitedFgsInfo fgsInfo) {
-        final long timeLimit;
-        switch (ams.mServices.getTimeLimitedFgsType(fgsType)) {
-            case ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROCESSING:
-                timeLimit = ams.mConstants.mMediaProcessingFgsTimeoutDuration;
-                break;
-            case ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC:
-                timeLimit = ams.mConstants.mDataSyncFgsTimeoutDuration;
-                break;
-            // Add logic for time limits introduced in the future for other fgs types above.
-            default:
-                return Long.MAX_VALUE;
-        }
-        return fgsInfo.mLastFgsStartTime + Math.max(0, timeLimit - fgsInfo.mTotalRuntime);
-    }
-
     private boolean isAppAlive() {
         if (app == null) {
             return false;
diff --git a/services/core/java/com/android/server/am/flags.aconfig b/services/core/java/com/android/server/am/flags.aconfig
index 19be5f9..fb63ec6 100644
--- a/services/core/java/com/android/server/am/flags.aconfig
+++ b/services/core/java/com/android/server/am/flags.aconfig
@@ -106,3 +106,13 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+flag {
+    name: "migrate_full_oomadj_updates"
+    namespace: "backstage_power"
+    description: "Migrate full updates to partial updates where possible"
+    bug: "324915545"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
index cd5d0c8..ff1e5d5 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
@@ -16,13 +16,14 @@
 
 package com.android.server.biometrics.log;
 
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_START;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.hardware.SensorManager;
 import android.hardware.biometrics.BiometricConstants;
 import android.hardware.biometrics.BiometricsProtoEnums;
-import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
 import android.util.Slog;
 
@@ -137,7 +138,7 @@
         final boolean isFingerprint = mStatsModality == BiometricsProtoEnums.MODALITY_FINGERPRINT;
         if (isFace || isFingerprint) {
             if ((isFingerprint && acquiredInfo == FingerprintManager.FINGERPRINT_ACQUIRED_START)
-                    || (isFace && acquiredInfo == FaceManager.FACE_ACQUIRED_START)) {
+                    || (isFace && acquiredInfo == FACE_ACQUIRED_START)) {
                 mFirstAcquireTimeMs = System.currentTimeMillis();
             }
         } else if (acquiredInfo == BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index 8d32235..ef7abdd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -17,6 +17,9 @@
 package com.android.server.biometrics.sensors.face.aidl;
 
 import static android.adaptiveauth.Flags.reportBiometricAuthAttempts;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_NOT_DETECTED;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_SENSOR_DIRTY;
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_UNKNOWN;
 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR;
 import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_VENDOR_BASE;
 import static android.hardware.face.FaceManager.getAuthHelpMessage;
@@ -43,7 +46,6 @@
 import android.hardware.biometrics.face.IFace;
 import android.hardware.face.FaceAuthenticateOptions;
 import android.hardware.face.FaceAuthenticationFrame;
-import android.hardware.face.FaceManager;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Slog;
@@ -90,8 +92,8 @@
     private final SensorPrivacyManager mSensorPrivacyManager;
     @NonNull
     private final AuthenticationStateListeners mAuthenticationStateListeners;
-    @FaceManager.FaceAcquired
-    private int mLastAcquire = FaceManager.FACE_ACQUIRED_UNKNOWN;
+    @BiometricFaceConstants.FaceAcquired
+    private int mLastAcquire = FACE_ACQUIRED_UNKNOWN;
 
     public FaceAuthenticationClient(@NonNull Context context,
             @NonNull Supplier<AidlSession> lazyDaemon,
@@ -232,9 +234,9 @@
     public boolean wasUserDetected() {
         // Do not provide haptic feedback if the user was not detected, and an error (usually
         // ERROR_TIMEOUT) is received.
-        return mLastAcquire != FaceManager.FACE_ACQUIRED_NOT_DETECTED
-                && mLastAcquire != FaceManager.FACE_ACQUIRED_SENSOR_DIRTY
-                && mLastAcquire != FaceManager.FACE_ACQUIRED_UNKNOWN;
+        return mLastAcquire != FACE_ACQUIRED_NOT_DETECTED
+                && mLastAcquire != FACE_ACQUIRED_SENSOR_DIRTY
+                && mLastAcquire != FACE_ACQUIRED_UNKNOWN;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 6b99493..559462a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -16,6 +16,8 @@
 
 package com.android.server.biometrics.sensors.face.aidl;
 
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -28,7 +30,6 @@
 import android.hardware.biometrics.face.IFace;
 import android.hardware.biometrics.face.ISession;
 import android.hardware.biometrics.face.SensorProps;
-import android.hardware.face.FaceManager;
 import android.hardware.face.FaceSensorPropertiesInternal;
 import android.os.Binder;
 import android.os.Handler;
@@ -296,7 +297,7 @@
         if (client != null && client.isInterruptable()) {
             Slog.e(TAG, "Sending face hardware unavailable error for client: " + client);
             final ErrorConsumer errorConsumer = (ErrorConsumer) client;
-            errorConsumer.onError(FaceManager.FACE_ERROR_HW_UNAVAILABLE,
+            errorConsumer.onError(FACE_ERROR_HW_UNAVAILABLE,
                     0 /* vendorCode */);
 
             FrameworkStatsLog.write(FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED,
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index a818eab..816242d 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -205,7 +205,7 @@
             Intent intent = new Intent(DreamService.SERVICE_INTERFACE);
             intent.setComponent(name);
             intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-            intent.putExtra(DreamService.EXTRA_DREAM_OVERLAY_COMPONENT, overlayComponentName);
+            DreamService.setDreamOverlayComponent(intent, overlayComponentName);
             try {
                 if (!mContext.bindServiceAsUser(intent, mCurrentDream,
                         Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 8686e9a..39f3121 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -2617,19 +2617,6 @@
         mBatteryController.notifyStylusGestureStarted(deviceId, eventTime);
     }
 
-    // Native callback.
-    @SuppressWarnings("unused")
-    private int getPackageUid(String pkg) {
-        if (TextUtils.isEmpty(pkg)) {
-            return Process.INVALID_UID;
-        }
-        try {
-            return mContext.getPackageManager().getPackageUid(pkg, 0 /*flags*/);
-        } catch (PackageManager.NameNotFoundException e) {
-            return Process.INVALID_UID;
-        }
-    }
-
     /**
      * Flatten a map into a string list, with value positioned directly next to the
      * key.
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 7bd47f5..44a200e 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -6419,7 +6419,7 @@
                             nextEnabledImeIds[i] = nextEnabledImes.get(i).getId();
                         }
                         settings.putEnabledInputMethodsStr(InputMethodUtils.concatEnabledImeIds(
-                                settings.getEnabledInputMethodsStr(), nextEnabledImeIds));
+                                "", nextEnabledImeIds));
 
                         // Reset selected IME.
                         settings.putSelectedInputMethod(nextIme);
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index e196dee..5731161 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -922,7 +922,7 @@
     }
 
     /**
-     * Handles a message deliveyr status from a Context Hub.
+     * Handles a message delivery status from a Context Hub.
      *
      * @param messageDeliveryStatus     The message delivery status to deliver.
      */
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index e5807e8..54303c0 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -1082,7 +1082,8 @@
             int keyguardCredentialsType = lockPatternUtilsToKeyguardType(savedCredentialType);
             try (LockscreenCredential credential =
                     createLockscreenCredential(keyguardCredentialsType, decryptedCredentials)) {
-                // TODO(b/254335492): remove decryptedCredentials
+                Arrays.fill(decryptedCredentials, (byte) 0);
+                decryptedCredentials = null;
                 VerifyCredentialResponse verifyResponse =
                         lockSettingsService.verifyCredential(credential, userId, 0);
                 return handleVerifyCredentialResponse(verifyResponse, userId);
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index d41727f..2e25ad8 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -573,12 +573,16 @@
                     (scanFlags & SCAN_DONT_KILL_APP) != 0 /* retainImplicitGrantOnReplace */);
             mPm.addAllPackageProperties(pkg);
 
-            if (oldPkgSetting == null || oldPkgSetting.getPkg() == null) {
-                mPm.mDomainVerificationManager.addPackage(pkgSetting,
-                        request.getPreVerifiedDomains());
-            } else {
-                mPm.mDomainVerificationManager.migrateState(oldPkgSetting, pkgSetting,
-                        request.getPreVerifiedDomains());
+            // Only verify app links for non-archival installations, otherwise there won't be any
+            // declared app links.
+            if (!request.isArchived()) {
+                if (oldPkgSetting == null || oldPkgSetting.getPkg() == null) {
+                    mPm.mDomainVerificationManager.addPackage(pkgSetting,
+                            request.getPreVerifiedDomains());
+                } else {
+                    mPm.mDomainVerificationManager.migrateState(oldPkgSetting, pkgSetting,
+                            request.getPreVerifiedDomains());
+                }
             }
 
             int collectionSize = ArrayUtils.size(pkg.getInstrumentations());
@@ -830,7 +834,7 @@
             doRestore = performRollbackManagerRestore(userId, token, request);
         }
 
-        if (succeeded && !request.hasPostInstallRunnable()) {
+        if (succeeded && doRestore && !request.hasPostInstallRunnable()) {
             boolean hasNeverBeenRestored =
                     packageSetting != null && packageSetting.isPendingRestore();
             request.setPostInstallRunnable(() -> {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 0f868eb..1309e44 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3243,6 +3243,9 @@
         if (pkg.isForceQueryableOverride()) {
             serializer.attributeBoolean(null, "forceQueryable", true);
         }
+        if (pkg.isPendingRestore()) {
+            serializer.attributeBoolean(null, "pendingRestore", true);
+        }
         if (pkg.isLoading()) {
             serializer.attributeBoolean(null, "isLoading", true);
         }
@@ -4046,6 +4049,7 @@
         PackageSetting packageSetting = null;
         long versionCode = 0;
         boolean installedForceQueryable = false;
+        boolean isPendingRestore = false;
         float loadingProgress = 0;
         long loadingCompletedTime = 0;
         UUID domainSetId;
@@ -4071,6 +4075,7 @@
             cpuAbiOverrideString = parser.getAttributeValue(null, "cpuAbiOverride");
             updateAvailable = parser.getAttributeBoolean(null, "updateAvailable", false);
             installedForceQueryable = parser.getAttributeBoolean(null, "forceQueryable", false);
+            isPendingRestore = parser.getAttributeBoolean(null, "pendingRestore", false);
             loadingProgress = parser.getAttributeFloat(null, "loadingProgress", 0);
             loadingCompletedTime = parser.getAttributeLongHex(null, "loadingCompletedTime", 0);
 
@@ -4244,6 +4249,7 @@
                     .setSecondaryCpuAbi(secondaryCpuAbiString)
                     .setUpdateAvailable(updateAvailable)
                     .setForceQueryableOverride(installedForceQueryable)
+                    .setPendingRestore(isPendingRestore)
                     .setLoadingProgress(loadingProgress)
                     .setLoadingCompletedTime(loadingCompletedTime)
                     .setAppMetadataFilePath(appMetadataFilePath)
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index fde49d2..5fa8856 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -129,6 +129,7 @@
     private final WindowManagerPolicy mPolicy;
     private final FaceDownDetector mFaceDownDetector;
     private final ScreenUndimDetector mScreenUndimDetector;
+    private final WakefulnessSessionObserver mWakefulnessSessionObserver;
     private final ActivityManagerInternal mActivityManagerInternal;
     private final InputManagerInternal mInputManagerInternal;
     private final InputMethodManagerInternal mInputMethodManagerInternal;
@@ -197,6 +198,7 @@
         mPolicy = policy;
         mFaceDownDetector = faceDownDetector;
         mScreenUndimDetector = screenUndimDetector;
+        mWakefulnessSessionObserver = new WakefulnessSessionObserver(mContext, null);
         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
         mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
@@ -286,6 +288,8 @@
         }
 
         mWakeLockLog.onWakeLockAcquired(tag, ownerUid, flags);
+
+        mWakefulnessSessionObserver.onWakeLockAcquired(flags);
     }
 
     public void onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource,
@@ -386,6 +390,16 @@
     public void onWakeLockReleased(int flags, String tag, String packageName,
             int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
             IWakeLockCallback callback) {
+        onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
+                callback, ScreenTimeoutOverridePolicy.RELEASE_REASON_UNKNOWN);
+    }
+
+    /**
+     * Called when a wake lock is released.
+     */
+    public void onWakeLockReleased(int flags, String tag, String packageName,
+            int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
+            IWakeLockCallback callback, int releaseReason) {
         if (DEBUG) {
             Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
                     + "\", packageName=" + packageName
@@ -409,6 +423,8 @@
             }
         }
         mWakeLockLog.onWakeLockReleased(tag, ownerUid);
+
+        mWakefulnessSessionObserver.onWakeLockReleased(flags, releaseReason);
     }
 
     /** Shows the keyguard without requesting the device to immediately lock. */
@@ -670,6 +686,8 @@
             interactivity.changeStartTime = eventTime;
             interactivity.isChanging = true;
             handleEarlyInteractiveChange(groupId);
+            mWakefulnessSessionObserver.onWakefulnessChangeStarted(groupId, wakefulness,
+                    changeReason, eventTime);
         }
     }
 
@@ -680,6 +698,7 @@
      */
     public void onGroupRemoved(int groupId) {
         mInteractivityByGroupId.remove(groupId);
+        mWakefulnessSessionObserver.removePowerGroup(groupId);
     }
 
     /**
@@ -693,6 +712,8 @@
 
         try {
             mBatteryStats.noteUserActivity(uid, event);
+            mWakefulnessSessionObserver.notifyUserActivity(
+                    SystemClock.uptimeMillis(), displayGroupId, event);
         } catch (RemoteException ex) {
             // Ignore
         }
@@ -798,6 +819,8 @@
         if (mWakeLockLog != null) {
             mWakeLockLog.dump(pw);
         }
+
+        mWakefulnessSessionObserver.dump(pw);
     }
 
     private void updatePendingBroadcastLocked() {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index eb1f720..bbb59ce 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -231,7 +231,7 @@
 
     // Default timeout in milliseconds.  This is only used until the settings
     // provider populates the actual default value (R.integer.def_screen_off_timeout).
-    private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000;
+    static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000;
     private static final int DEFAULT_SLEEP_TIMEOUT = -1;
 
     // Screen brightness boost timeout.
@@ -1417,8 +1417,9 @@
             updateSettingsLocked();
             if (mFeatureFlags.isEarlyScreenTimeoutDetectorEnabled()) {
                 mScreenTimeoutOverridePolicy = new ScreenTimeoutOverridePolicy(mContext,
-                        mMinimumScreenOffTimeoutConfig, () -> {
+                        mMinimumScreenOffTimeoutConfig, (releaseReason) -> {
                     Message msg = mHandler.obtainMessage(MSG_RELEASE_ALL_OVERRIDE_WAKE_LOCKS);
+                    msg.arg1 = releaseReason;
                     mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
                 });
             }
@@ -1827,6 +1828,12 @@
 
     @GuardedBy("mLock")
     private void removeWakeLockNoUpdateLocked(WakeLock wakeLock, int index) {
+        removeWakeLockNoUpdateLocked(wakeLock, index,
+                ScreenTimeoutOverridePolicy.RELEASE_REASON_UNKNOWN);
+    }
+
+    @GuardedBy("mLock")
+    private void removeWakeLockNoUpdateLocked(WakeLock wakeLock, int index, int releaseReason) {
         mWakeLocks.remove(index);
         UidState state = wakeLock.mUidState;
         state.mNumWakeLocks--;
@@ -1835,7 +1842,7 @@
             mUidState.remove(state.mUid);
         }
 
-        notifyWakeLockReleasedLocked(wakeLock);
+        notifyWakeLockReleasedLocked(wakeLock, releaseReason);
         applyWakeLockFlagsOnReleaseLocked(wakeLock);
         mDirty |= DIRTY_WAKE_LOCKS;
     }
@@ -2001,12 +2008,17 @@
 
     @GuardedBy("mLock")
     private void notifyWakeLockReleasedLocked(WakeLock wakeLock) {
+        notifyWakeLockReleasedLocked(wakeLock, ScreenTimeoutOverridePolicy.RELEASE_REASON_UNKNOWN);
+    }
+
+    @GuardedBy("mLock")
+    private void notifyWakeLockReleasedLocked(WakeLock wakeLock, int releaseReason) {
         if (mSystemReady && wakeLock.mNotifiedAcquired) {
             wakeLock.mNotifiedAcquired = false;
             wakeLock.mAcquireTime = 0;
             mNotifier.onWakeLockReleased(wakeLock.mFlags, wakeLock.mTag,
                     wakeLock.mPackageName, wakeLock.mOwnerUid, wakeLock.mOwnerPid,
-                    wakeLock.mWorkSource, wakeLock.mHistoryTag, wakeLock.mCallback);
+                    wakeLock.mWorkSource, wakeLock.mHistoryTag, wakeLock.mCallback, releaseReason);
             notifyWakeLockLongFinishedLocked(wakeLock);
         }
     }
@@ -5345,7 +5357,7 @@
                     handleAttentiveTimeout();
                     break;
                 case MSG_RELEASE_ALL_OVERRIDE_WAKE_LOCKS:
-                    releaseAllOverrideWakeLocks();
+                    releaseAllOverrideWakeLocks(msg.arg1);
                     break;
             }
 
@@ -7269,7 +7281,7 @@
         return false;
     }
 
-    private void releaseAllOverrideWakeLocks() {
+    private void releaseAllOverrideWakeLocks(int releaseReason) {
         synchronized (mLock) {
             final int size = mWakeLocks.size();
             boolean change = false;
@@ -7277,7 +7289,7 @@
                 final WakeLock wakeLock = mWakeLocks.get(i);
                 if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
                         == PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK) {
-                    removeWakeLockNoUpdateLocked(wakeLock, i);
+                    removeWakeLockNoUpdateLocked(wakeLock, i, releaseReason);
                     change = true;
                 }
             }
diff --git a/services/core/java/com/android/server/power/ScreenTimeoutOverridePolicy.java b/services/core/java/com/android/server/power/ScreenTimeoutOverridePolicy.java
index adde518..dcb3c39 100644
--- a/services/core/java/com/android/server/power/ScreenTimeoutOverridePolicy.java
+++ b/services/core/java/com/android/server/power/ScreenTimeoutOverridePolicy.java
@@ -23,6 +23,7 @@
 import static com.android.server.power.PowerManagerService.WAKE_LOCK_SCREEN_DIM;
 import static com.android.server.power.PowerManagerService.WAKE_LOCK_SCREEN_TIMEOUT_OVERRIDE;
 
+import android.annotation.IntDef;
 import android.content.Context;
 import android.os.PowerManager;
 import android.util.IndentingPrintWriter;
@@ -31,6 +32,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
   * Policy that handle the screen timeout override wake lock behavior.
@@ -50,25 +53,62 @@
     public static final int RELEASE_REASON_NON_INTERACTIVE = 1;
 
     /**
-     * Release reason code: Release because user activity occurred.
-     */
-    public static final int RELEASE_REASON_USER_ACTIVITY = 2;
-    /**
      * Release reason code: Release because a screen lock is acquired.
      */
-    public static final int RELEASE_REASON_SCREEN_LOCK = 3;
+    public static final int RELEASE_REASON_SCREEN_LOCK = 2;
+
+    /**
+     * Release reason code: Release because user activity attention occurs.
+     */
+    public static final int RELEASE_REASON_USER_ACTIVITY_ATTENTION = 3;
+
+    /**
+     * Release reason code: Release because user activity other occurs.
+     */
+    public static final int RELEASE_REASON_USER_ACTIVITY_OTHER = 4;
+
+    /**
+     * Release reason code: Release because user activity button occurs.
+     */
+    public static final int RELEASE_REASON_USER_ACTIVITY_BUTTON = 5;
+
+    /**
+     * Release reason code: Release because user activity touch occurs.
+     */
+    public static final int RELEASE_REASON_USER_ACTIVITY_TOUCH = 6;
+
+    /**
+     * Release reason code: Release because user activity accessibility occurs.
+     */
+    public static final int RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY = 7;
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = { "RELEASE_REASON_" }, value = {
+            RELEASE_REASON_UNKNOWN,
+            RELEASE_REASON_NON_INTERACTIVE,
+            RELEASE_REASON_SCREEN_LOCK,
+            RELEASE_REASON_USER_ACTIVITY_ATTENTION,
+            RELEASE_REASON_USER_ACTIVITY_OTHER,
+            RELEASE_REASON_USER_ACTIVITY_BUTTON,
+            RELEASE_REASON_USER_ACTIVITY_TOUCH,
+            RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ReleaseReason{}
 
     // The screen timeout override config in milliseconds.
     private long mScreenTimeoutOverrideConfig;
 
     // The last reason that wake locks had been released by service.
-    private int mLastAutoReleaseReason = RELEASE_REASON_UNKNOWN;
+    private @ReleaseReason int mLastAutoReleaseReason = RELEASE_REASON_UNKNOWN;
 
     interface PolicyCallback {
         /**
          * Notify {@link PowerManagerService} to release all override wake locks.
          */
-        void releaseAllScreenTimeoutOverrideWakelocks();
+        void releaseAllScreenTimeoutOverrideWakelocks(@ReleaseReason int reason);
     }
     private PolicyCallback mPolicyCallback;
 
@@ -110,11 +150,20 @@
 
         switch (event) {
             case PowerManager.USER_ACTIVITY_EVENT_ATTENTION:
+                releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY_ATTENTION);
+                return;
             case PowerManager.USER_ACTIVITY_EVENT_OTHER:
+                releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY_OTHER);
+                return;
             case PowerManager.USER_ACTIVITY_EVENT_BUTTON:
+                releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY_BUTTON);
+                return;
             case PowerManager.USER_ACTIVITY_EVENT_TOUCH:
+                releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY_TOUCH);
+                return;
             case PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY:
-                releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY);
+                releaseAllWakeLocks(RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY);
+                return;
         }
     }
 
@@ -154,8 +203,8 @@
                 + " (reason=" + mLastAutoReleaseReason + ")");
     }
 
-    private void releaseAllWakeLocks(int reason) {
-        mPolicyCallback.releaseAllScreenTimeoutOverrideWakelocks();
+    private void releaseAllWakeLocks(@ReleaseReason int reason) {
+        mPolicyCallback.releaseAllScreenTimeoutOverrideWakelocks(reason);
         mLastAutoReleaseReason = reason;
         logReleaseReason();
     }
diff --git a/services/core/java/com/android/server/power/WakefulnessSessionObserver.java b/services/core/java/com/android/server/power/WakefulnessSessionObserver.java
new file mode 100644
index 0000000..d57cd5d
--- /dev/null
+++ b/services/core/java/com/android/server/power/WakefulnessSessionObserver.java
@@ -0,0 +1,595 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.power;
+
+import static android.os.PowerManager.USER_ACTIVITY_EVENT_OTHER;
+import static android.os.PowerManagerInternal.isInteractive;
+
+import static com.android.server.power.PowerManagerService.DEFAULT_SCREEN_OFF_TIMEOUT;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_NON_INTERACTIVE;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_SCREEN_LOCK;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_UNKNOWN;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_ATTENTION;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_BUTTON;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_OTHER;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_TOUCH;
+
+import android.annotation.IntDef;
+import android.app.ActivityManager;
+import android.app.SynchronousUserSwitchObserver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.PowerManagerInternal;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.IndentingPrintWriter;
+import android.util.SparseArray;
+import android.view.Display;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Observe the wakefulness session of the device, tracking the reason and the
+ * last user activity when the interactive state is off.
+ */
+public class WakefulnessSessionObserver {
+    private static final String TAG = "WakefulnessSessionObserver";
+
+    private static final int OFF_REASON_UNKNOWN = FrameworkStatsLog
+            .SCREEN_INTERACTIVE_SESSION_REPORTED__INTERACTIVE_STATE_OFF_REASON__UNKNOWN;
+    private static final int OFF_REASON_TIMEOUT = FrameworkStatsLog
+            .SCREEN_INTERACTIVE_SESSION_REPORTED__INTERACTIVE_STATE_OFF_REASON__TIMEOUT;
+    @VisibleForTesting
+    protected static final int OFF_REASON_POWER_BUTTON = FrameworkStatsLog
+            .SCREEN_INTERACTIVE_SESSION_REPORTED__INTERACTIVE_STATE_OFF_REASON__POWER_BUTTON;
+
+    /**
+     * Interactive off reason
+     * {@link android.os.statsd.power.ScreenInteractiveSessionReported.InteractiveStateOffReason}.
+     */
+    @IntDef(prefix = {"OFF_REASON_"}, value = {
+            OFF_REASON_UNKNOWN,
+            OFF_REASON_TIMEOUT,
+            OFF_REASON_POWER_BUTTON
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface OffReason {}
+
+    private static final int OVERRIDE_OUTCOME_UNKNOWN = FrameworkStatsLog
+            .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__UNKNOWN;
+    @VisibleForTesting
+    protected static final int OVERRIDE_OUTCOME_TIMEOUT_SUCCESS = FrameworkStatsLog
+            .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__TIMEOUT_SUCCESS;
+    @VisibleForTesting
+    protected static final int OVERRIDE_OUTCOME_TIMEOUT_USER_INITIATED_REVERT = FrameworkStatsLog
+            .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__TIMEOUT_USER_INITIATED_REVERT;
+    private static final int OVERRIDE_OUTCOME_CANCEL_CLIENT_API_CALL = FrameworkStatsLog
+            .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__CANCEL_CLIENT_API_CALL;
+    @VisibleForTesting
+    protected static final int OVERRIDE_OUTCOME_CANCEL_USER_INTERACTION = FrameworkStatsLog
+            .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__CANCEL_USER_INTERACTION;
+    @VisibleForTesting
+    protected static final int OVERRIDE_OUTCOME_CANCEL_POWER_BUTTON = FrameworkStatsLog
+            .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__CANCEL_POWER_BUTTON;
+    private static final int OVERRIDE_OUTCOME_CANCEL_CLIENT_DISCONNECT = FrameworkStatsLog
+            .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__CANCEL_CLIENT_DISCONNECTED;
+    private static final int OVERRIDE_OUTCOME_CANCEL_OTHER = FrameworkStatsLog
+            .SCREEN_TIMEOUT_OVERRIDE_REPORTED__OVERRIDE_OUTCOME__CANCEL_OTHER;
+
+    /**
+     * Override Outcome
+     * {@link android.os.statsd.power.ScreenTimeoutOverrideReported.OverrideOutcome}.
+     */
+    @IntDef(prefix = {"OVERRIDE_OUTCOME_"}, value = {
+            OVERRIDE_OUTCOME_UNKNOWN,
+            OVERRIDE_OUTCOME_TIMEOUT_SUCCESS,
+            OVERRIDE_OUTCOME_TIMEOUT_USER_INITIATED_REVERT,
+            OVERRIDE_OUTCOME_CANCEL_CLIENT_API_CALL,
+            OVERRIDE_OUTCOME_CANCEL_USER_INTERACTION,
+            OVERRIDE_OUTCOME_CANCEL_POWER_BUTTON,
+            OVERRIDE_OUTCOME_CANCEL_CLIENT_DISCONNECT,
+            OVERRIDE_OUTCOME_CANCEL_OTHER
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface OverrideOutcome {}
+
+    private static final int DEFAULT_USER_ACTIVITY = USER_ACTIVITY_EVENT_OTHER;
+    private static final long TIMEOUT_USER_INITIATED_REVERT_THRESHOLD_MILLIS = 5000L;
+    private static final long SEND_OVERRIDE_TIMEOUT_LOG_THRESHOLD_MILLIS = 1000L;
+
+    private Context mContext;
+    private int mScreenOffTimeoutMs;
+    private int mOverrideTimeoutMs = 0;
+    @VisibleForTesting
+    protected final SparseArray<WakefulnessSessionPowerGroup> mPowerGroups = new SparseArray<>();
+    @VisibleForTesting
+    protected WakefulnessSessionFrameworkStatsLogger mWakefulnessSessionFrameworkStatsLogger;
+    private final Clock mClock;
+    private final Object mLock = new Object();
+
+    public WakefulnessSessionObserver(Context context, Injector injector) {
+        if (injector == null) {
+            injector = new Injector();
+        }
+
+        mContext = context;
+        mWakefulnessSessionFrameworkStatsLogger = injector
+                .getWakefulnessSessionFrameworkStatsLogger();
+        mClock = injector.getClock();
+        updateSettingScreenOffTimeout(context);
+
+        try {
+            final UserSwitchObserver observer = new UserSwitchObserver();
+            ActivityManager.getService().registerUserSwitchObserver(observer, TAG);
+        } catch (RemoteException e) {
+            // Shouldn't happen since in-process.
+        }
+
+        mOverrideTimeoutMs = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_screenTimeoutOverride);
+
+        mContext.getContentResolver()
+                .registerContentObserver(
+                        Settings.System.getUriFor(Settings.System.SCREEN_OFF_TIMEOUT),
+                        false,
+                        new ContentObserver(new Handler(mContext.getMainLooper())) {
+                            @Override
+                            public void onChange(boolean selfChange) {
+                                updateSettingScreenOffTimeout(mContext);
+                            }
+                        },
+                        UserHandle.USER_ALL);
+
+        mPowerGroups.append(
+                Display.DEFAULT_DISPLAY_GROUP,
+                new WakefulnessSessionPowerGroup(Display.DEFAULT_DISPLAY_GROUP));
+    }
+
+    /**
+     * Track the user activity event.
+     *
+     * @param eventTime Activity time, in uptime millis.
+     * @param powerGroupId Power Group Id for this user activity
+     * @param event Activity type as defined in {@link PowerManager}. {@link
+     *     android.hardware.display.DisplayManagerInternal.DisplayPowerRequest}
+     */
+    public void notifyUserActivity(
+            long eventTime, int powerGroupId, @PowerManager.UserActivityEvent int event) {
+        if (!mPowerGroups.contains(powerGroupId)) {
+            mPowerGroups.append(powerGroupId, new WakefulnessSessionPowerGroup(powerGroupId));
+        }
+        mPowerGroups.get(powerGroupId).notifyUserActivity(eventTime, event);
+    }
+
+    /**
+     * Track the system wakefulness
+     *
+     * @param powerGroupId Power Group Id for this wakefulness changes
+     * @param wakefulness Wakefulness as defined in {@link PowerManagerInternal}
+     * @param changeReason Reason of the go to sleep in
+     * {@link PowerManager.GoToSleepReason} or {@link PowerManager.WakeReason}
+     * @param eventTime timestamp of the wakefulness changes
+     */
+    public void onWakefulnessChangeStarted(int powerGroupId, int wakefulness, int changeReason,
+            long eventTime) {
+        if (!mPowerGroups.contains(powerGroupId)) {
+            mPowerGroups.append(powerGroupId, new WakefulnessSessionPowerGroup(powerGroupId));
+        }
+        mPowerGroups.get(powerGroupId).onWakefulnessChangeStarted(wakefulness, changeReason,
+                eventTime);
+    }
+
+    /**
+     * Track the acquired wakelocks
+     *
+     * @param flags wakelocks to be acquired {@link PowerManager}
+     */
+    public void onWakeLockAcquired(int flags) {
+        int maskedFlag = flags & PowerManager.WAKE_LOCK_LEVEL_MASK;
+        if (maskedFlag == PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK) {
+            for (int idx = 0; idx < mPowerGroups.size(); idx++) {
+                mPowerGroups.valueAt(idx).acquireTimeoutOverrideWakeLock();
+            }
+        }
+    }
+
+    /**
+     * Track the released wakelocks
+     *
+     * @param flags wakelocks to be released {@link PowerManager}
+     * @param releaseReason the reason to release wakelock
+     * {@link ScreenTimeoutOverridePolicy.ReleaseReason}
+     */
+    public void onWakeLockReleased(int flags, int releaseReason) {
+        int maskedFlag = flags & PowerManager.WAKE_LOCK_LEVEL_MASK;
+        if (maskedFlag == PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK) {
+            for (int idx = 0; idx < mPowerGroups.size(); idx++) {
+                mPowerGroups.valueAt(idx).releaseTimeoutOverrideWakeLock(releaseReason);
+            }
+        }
+    }
+
+    /**
+     * Remove the inactive power group
+     *
+     * @param powerGroupId Power Group Id that should be removed
+     */
+    public void removePowerGroup(int powerGroupId) {
+        if (mPowerGroups.contains((powerGroupId))) {
+            mPowerGroups.delete(powerGroupId);
+        }
+    }
+
+    void dump(PrintWriter writer) {
+        writer.println();
+        writer.println("Wakefulness Session Observer:");
+        writer.println("default timeout: " + mScreenOffTimeoutMs);
+        writer.println("override timeout: " + mOverrideTimeoutMs);
+        IndentingPrintWriter indentingPrintWriter = new IndentingPrintWriter(writer);
+        indentingPrintWriter.increaseIndent();
+        for (int idx = 0; idx < mPowerGroups.size(); idx++) {
+            mPowerGroups.valueAt(idx).dump(indentingPrintWriter);
+        }
+        writer.println();
+    }
+
+    private void updateSettingScreenOffTimeout(Context context) {
+        synchronized (mLock) {
+            mScreenOffTimeoutMs = Settings.System.getIntForUser(
+                    context.getContentResolver(),
+                    Settings.System.SCREEN_OFF_TIMEOUT,
+                    DEFAULT_SCREEN_OFF_TIMEOUT,
+                    UserHandle.USER_CURRENT);
+        }
+    }
+
+    private int getScreenOffTimeout() {
+        synchronized (mLock) {
+            return mScreenOffTimeoutMs;
+        }
+    }
+
+    /** Screen Session by each power group */
+    @VisibleForTesting
+    protected class WakefulnessSessionPowerGroup {
+        private static final long TIMEOUT_OFF_RESET_TIMESTAMP = -1;
+
+        private int mPowerGroupId;
+        private int mCurrentWakefulness;
+        private boolean mIsInteractive = false;
+        // state on start timestamp: will be used in state off to calculate the duration of state on
+        private long mInteractiveStateOnStartTimestamp;
+        @VisibleForTesting
+        protected long mCurrentUserActivityTimestamp;
+        @VisibleForTesting
+        protected @PowerManager.UserActivityEvent int mCurrentUserActivityEvent;
+        @VisibleForTesting
+        protected long mPrevUserActivityTimestamp;
+        @VisibleForTesting
+        protected @PowerManager.UserActivityEvent int mPrevUserActivityEvent;
+        // to track the Override Timeout is set (that is, on SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK)
+        private int mTimeoutOverrideWakeLockCounter = 0;
+        // The timestamp when Override Timeout is set to false
+        private @ScreenTimeoutOverridePolicy.ReleaseReason int mTimeoutOverrideReleaseReason;
+        // The timestamp when state off by timeout occurs
+        // will set TIMEOUT_OFF_RESET_TIMESTAMP if state on or state off by power button
+        private long mTimeoutOffTimestamp;
+        // The timestamp for the latest logTimeoutOverrideEvent calling
+        private long mSendOverrideTimeoutLogTimestamp;
+
+        public WakefulnessSessionPowerGroup(int powerGroupId) {
+            mCurrentUserActivityEvent = DEFAULT_USER_ACTIVITY;
+            mCurrentUserActivityTimestamp = -1;
+            mPrevUserActivityEvent = DEFAULT_USER_ACTIVITY;
+            mPrevUserActivityTimestamp = -1;
+            mPowerGroupId = powerGroupId;
+        }
+
+        public void notifyUserActivity(long eventTime, @PowerManager.UserActivityEvent int event) {
+            // only track when user activity changes
+            if (event == mCurrentUserActivityEvent) {
+                return;
+            }
+            mPrevUserActivityEvent = mCurrentUserActivityEvent;
+            mCurrentUserActivityEvent = event;
+            mPrevUserActivityTimestamp = mCurrentUserActivityTimestamp;
+            mCurrentUserActivityTimestamp = eventTime;
+        }
+
+        public void onWakefulnessChangeStarted(int wakefulness, int changeReason, long eventTime) {
+            mCurrentWakefulness = wakefulness;
+            if (mIsInteractive == isInteractive(wakefulness)) {
+                return;
+            }
+
+            mIsInteractive = isInteractive(wakefulness);
+            if (mIsInteractive) {
+                mInteractiveStateOnStartTimestamp = eventTime;
+
+                // Log the outcome of screen timeout override (USER INITIATED REVERT),
+                // when user initiates to revert the screen off state in a short period.
+                if (mTimeoutOffTimestamp != TIMEOUT_OFF_RESET_TIMESTAMP) {
+                    long offToOnDurationMs = eventTime - mTimeoutOffTimestamp;
+                    if (offToOnDurationMs < TIMEOUT_USER_INITIATED_REVERT_THRESHOLD_MILLIS) {
+                        mWakefulnessSessionFrameworkStatsLogger.logTimeoutOverrideEvent(
+                                mPowerGroupId,
+                                OVERRIDE_OUTCOME_TIMEOUT_USER_INITIATED_REVERT,
+                                mOverrideTimeoutMs,
+                                getScreenOffTimeout());
+                        mSendOverrideTimeoutLogTimestamp = eventTime;
+                    }
+                    mTimeoutOffTimestamp = TIMEOUT_OFF_RESET_TIMESTAMP;
+                }
+            } else {
+                int lastUserActivity = mCurrentUserActivityEvent;
+                long lastUserActivityDurationMs = eventTime - mCurrentUserActivityTimestamp;
+                @OffReason int interactiveStateOffReason = OFF_REASON_UNKNOWN;
+                int reducedInteractiveStateOnDurationMs = 0;
+
+                if (changeReason == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON) {
+                    interactiveStateOffReason = OFF_REASON_POWER_BUTTON;
+
+                    // Power Off will be triggered by USER_ACTIVITY_EVENT_BUTTON
+                    // The metric wants to record the previous activity before EVENT_BUTTON
+                    lastUserActivity = mPrevUserActivityEvent;
+                    lastUserActivityDurationMs = eventTime - mPrevUserActivityTimestamp;
+
+                    if (isInOverrideTimeout()
+                            || mTimeoutOverrideReleaseReason == RELEASE_REASON_USER_ACTIVITY_BUTTON
+                    ) {
+                        mWakefulnessSessionFrameworkStatsLogger.logTimeoutOverrideEvent(
+                                mPowerGroupId,
+                                OVERRIDE_OUTCOME_CANCEL_POWER_BUTTON,
+                                mOverrideTimeoutMs,
+                                getScreenOffTimeout());
+                        mSendOverrideTimeoutLogTimestamp = eventTime;
+                        mTimeoutOverrideReleaseReason = RELEASE_REASON_UNKNOWN; // reset the reason
+                    }
+                } else if (changeReason == PowerManager.GO_TO_SLEEP_REASON_TIMEOUT) {
+                    // Interactive Off reason is timeout
+                    interactiveStateOffReason = OFF_REASON_TIMEOUT;
+
+                    lastUserActivity = mCurrentUserActivityEvent;
+                    lastUserActivityDurationMs = eventTime - mCurrentUserActivityTimestamp;
+
+                    // Log the outcome of screen timeout override when the early screen
+                    // timeout has been done successfully.
+                    if (isInOverrideTimeout()) {
+                        reducedInteractiveStateOnDurationMs =
+                                getScreenOffTimeout() - mOverrideTimeoutMs;
+
+                        mWakefulnessSessionFrameworkStatsLogger.logTimeoutOverrideEvent(
+                                mPowerGroupId,
+                                OVERRIDE_OUTCOME_TIMEOUT_SUCCESS,
+                                mOverrideTimeoutMs,
+                                getScreenOffTimeout());
+                        mSendOverrideTimeoutLogTimestamp = eventTime;
+
+                        // Record a timestamp to track if the user initiates to revert from off
+                        // state instantly
+                        mTimeoutOffTimestamp = eventTime;
+                    }
+                }
+
+                long interactiveStateOnDurationMs =
+                        eventTime - mInteractiveStateOnStartTimestamp;
+                mWakefulnessSessionFrameworkStatsLogger.logSessionEvent(
+                        mPowerGroupId,
+                        interactiveStateOffReason,
+                        interactiveStateOnDurationMs,
+                        lastUserActivity,
+                        lastUserActivityDurationMs,
+                        reducedInteractiveStateOnDurationMs);
+            }
+        }
+
+        public void acquireTimeoutOverrideWakeLock() {
+            synchronized (mLock) {
+                mTimeoutOverrideWakeLockCounter++;
+            }
+        }
+
+        public void releaseTimeoutOverrideWakeLock(
+                @ScreenTimeoutOverridePolicy.ReleaseReason  int releaseReason) {
+            synchronized (mLock) {
+                mTimeoutOverrideWakeLockCounter--;
+            }
+
+            if (!isInOverrideTimeout()) {
+                mTimeoutOverrideReleaseReason = releaseReason;
+                long now = mClock.uptimeMillis();
+
+                // Log the outcome of screen timeout override (USER INTERACTIVE or DISCONNECT),
+                // when early screen timeout be canceled.
+                // Note: Set the threshold to avoid sending this log repeatly after other outcomes.
+                long sendOverrideTimeoutLogDuration = now - mSendOverrideTimeoutLogTimestamp;
+                boolean sendOverrideTimeoutLogSoon = sendOverrideTimeoutLogDuration
+                        < SEND_OVERRIDE_TIMEOUT_LOG_THRESHOLD_MILLIS;
+                if (!sendOverrideTimeoutLogSoon) {
+                    @OverrideOutcome int outcome = OVERRIDE_OUTCOME_UNKNOWN;
+                    switch (releaseReason) {
+                        case RELEASE_REASON_USER_ACTIVITY_ATTENTION:
+                        case RELEASE_REASON_USER_ACTIVITY_OTHER:
+                        case RELEASE_REASON_USER_ACTIVITY_BUTTON:
+                        case RELEASE_REASON_USER_ACTIVITY_TOUCH:
+                        case RELEASE_REASON_USER_ACTIVITY_ACCESSIBILITY:
+                            outcome = OVERRIDE_OUTCOME_CANCEL_USER_INTERACTION;
+                            break;
+                        case RELEASE_REASON_SCREEN_LOCK:
+                        case RELEASE_REASON_NON_INTERACTIVE:
+                            outcome = OVERRIDE_OUTCOME_CANCEL_CLIENT_DISCONNECT;
+                            break;
+                        default:
+                            outcome = OVERRIDE_OUTCOME_UNKNOWN;
+                    }
+                    mWakefulnessSessionFrameworkStatsLogger.logTimeoutOverrideEvent(
+                            mPowerGroupId,
+                            outcome,
+                            mOverrideTimeoutMs,
+                            getScreenOffTimeout());
+                }
+            }
+        }
+
+        @VisibleForTesting
+        protected boolean isInOverrideTimeout() {
+            synchronized (mLock) {
+                return (mTimeoutOverrideWakeLockCounter > 0);
+            }
+        }
+
+        void dump(IndentingPrintWriter writer) {
+            final long now = mClock.uptimeMillis();
+
+            writer.println("Wakefulness Session Power Group powerGroupId: " + mPowerGroupId);
+            writer.increaseIndent();
+            writer.println("current wakefulness: " + mCurrentWakefulness);
+            writer.println("current user activity event: " + mCurrentUserActivityEvent);
+            final long currentUserActivityDurationMs = now - mCurrentUserActivityTimestamp;
+            writer.println("current user activity duration: " + currentUserActivityDurationMs);
+            writer.println("previous user activity event: " + mPrevUserActivityEvent);
+            final long prevUserActivityDurationMs = now - mPrevUserActivityTimestamp;
+            writer.println("previous user activity duration: " + prevUserActivityDurationMs);
+            writer.println("is in override timeout: " + isInOverrideTimeout());
+            writer.decreaseIndent();
+        }
+    }
+
+    /** Log screen session atoms */
+    protected static class WakefulnessSessionFrameworkStatsLogger {
+        public void logSessionEvent(
+                int powerGroupId,
+                @OffReason int interactiveStateOffReason,
+                long interactiveStateOnDurationMs,
+                @PowerManager.UserActivityEvent int userActivityEvent,
+                long lastUserActivityEventDurationMs,
+                int reducedInteractiveStateOnDurationMs) {
+            int logUserActivityEvent = convertToLogUserActivityEvent(userActivityEvent);
+            FrameworkStatsLog.write(
+                    FrameworkStatsLog.SCREEN_INTERACTIVE_SESSION_REPORTED,
+                    powerGroupId,
+                    interactiveStateOffReason,
+                    interactiveStateOnDurationMs,
+                    logUserActivityEvent,
+                    lastUserActivityEventDurationMs,
+                    (long) reducedInteractiveStateOnDurationMs);
+        }
+
+        public void logTimeoutOverrideEvent(
+                int powerGroupId,
+                @OverrideOutcome int overrideOutcome,
+                int overrideTimeoutMs,
+                int defaultTimeoutMs) {
+            FrameworkStatsLog.write(
+                    FrameworkStatsLog.SCREEN_TIMEOUT_OVERRIDE_REPORTED,
+                    powerGroupId,
+                    overrideOutcome,
+                    (long) overrideTimeoutMs,
+                    (long) defaultTimeoutMs);
+        }
+
+        private static final int USER_ACTIVITY_OTHER = FrameworkStatsLog
+                .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__OTHER;
+
+        private static final int USER_ACTIVITY_BUTTON = FrameworkStatsLog
+                .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__BUTTON;
+
+        private static final int USER_ACTIVITY_TOUCH = FrameworkStatsLog
+                .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__TOUCH;
+
+        private static final int USER_ACTIVITY_ACCESSIBILITY = FrameworkStatsLog
+                .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__ACCESSIBILITY;
+        private static final int USER_ACTIVITY_ATTENTION = FrameworkStatsLog
+                .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__ATTENTION;
+        private static final int USER_ACTIVITY_FACE_DOWN = FrameworkStatsLog
+                .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__FACE_DOWN;
+
+        private static final int USER_ACTIVITY_DEVICE_STATE = FrameworkStatsLog
+                .SCREEN_INTERACTIVE_SESSION_REPORTED__LAST_USER_ACTIVITY_EVENT__DEVICE_STATE;
+
+        /**
+         * User Activity Event
+         * {@link android.os.statsd.power.ScreenInteractiveSessionReported.UserActivityEvent}.
+         */
+        @IntDef(prefix = {"USER_ACTIVITY_"}, value = {
+                USER_ACTIVITY_OTHER,
+                USER_ACTIVITY_BUTTON,
+                USER_ACTIVITY_TOUCH,
+                USER_ACTIVITY_ACCESSIBILITY,
+                USER_ACTIVITY_ATTENTION,
+                USER_ACTIVITY_FACE_DOWN,
+                USER_ACTIVITY_DEVICE_STATE,
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        private @interface UserActivityEvent {}
+
+        private @UserActivityEvent int convertToLogUserActivityEvent(
+                @PowerManager.UserActivityEvent int userActivity) {
+            switch (userActivity) {
+                case PowerManager.USER_ACTIVITY_EVENT_OTHER:
+                    return USER_ACTIVITY_OTHER;
+                case PowerManager.USER_ACTIVITY_EVENT_BUTTON:
+                    return USER_ACTIVITY_BUTTON;
+                case PowerManager.USER_ACTIVITY_EVENT_TOUCH:
+                    return USER_ACTIVITY_TOUCH;
+                case PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY:
+                    return USER_ACTIVITY_ACCESSIBILITY;
+                case PowerManager.USER_ACTIVITY_EVENT_ATTENTION:
+                    return USER_ACTIVITY_ATTENTION;
+                case PowerManager.USER_ACTIVITY_EVENT_FACE_DOWN:
+                    return USER_ACTIVITY_FACE_DOWN;
+                case PowerManager.USER_ACTIVITY_EVENT_DEVICE_STATE:
+                    return USER_ACTIVITY_DEVICE_STATE;
+            }
+            return USER_ACTIVITY_OTHER;
+        }
+    }
+
+    /** To observe and do actions if users switch */
+    private final class UserSwitchObserver extends SynchronousUserSwitchObserver {
+        @Override
+        public void onUserSwitching(int newUserId) throws RemoteException {
+            updateSettingScreenOffTimeout(mContext);
+        }
+    }
+
+    @VisibleForTesting
+    interface Clock {
+        long uptimeMillis();
+    }
+
+    @VisibleForTesting
+    static class Injector {
+        WakefulnessSessionFrameworkStatsLogger getWakefulnessSessionFrameworkStatsLogger() {
+            return new WakefulnessSessionFrameworkStatsLogger();
+        }
+
+        Clock getClock() {
+            return SystemClock::uptimeMillis;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java
index 6e17fd3..4ddd546 100644
--- a/services/core/java/com/android/server/power/hint/HintManagerService.java
+++ b/services/core/java/com/android/server/power/hint/HintManagerService.java
@@ -91,7 +91,7 @@
     @GuardedBy("mLock")
     private final ArrayMap<Integer, ArrayMap<IBinder, ArraySet<AppHintSession>>> mActiveSessions;
 
-    /** Lock to protect mActiveSessions. */
+    /** Lock to protect mActiveSessions and the UidObserver. */
     private final Object mLock = new Object();
 
     @GuardedBy("mNonIsolatedTidsLock")
@@ -318,11 +318,10 @@
 
     @VisibleForTesting
     final class MyUidObserver extends UidObserver {
-        private final Object mCacheLock = new Object();
-        @GuardedBy("mCacheLock")
+        @GuardedBy("mLock")
         private final SparseIntArray mProcStatesCache = new SparseIntArray();
         public boolean isUidForeground(int uid) {
-            synchronized (mCacheLock) {
+            synchronized (mLock) {
                 return mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND)
                         <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
             }
@@ -331,10 +330,8 @@
         @Override
         public void onUidGone(int uid, boolean disabled) {
             FgThread.getHandler().post(() -> {
-                synchronized (mCacheLock) {
-                    mProcStatesCache.delete(uid);
-                }
                 synchronized (mLock) {
+                    mProcStatesCache.delete(uid);
                     ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap = mActiveSessions.get(uid);
                     if (tokenMap == null) {
                         return;
@@ -357,7 +354,7 @@
         @Override
         public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
             FgThread.getHandler().post(() -> {
-                synchronized (mCacheLock) {
+                synchronized (mLock) {
                     if (powerhintThreadCleanup()) {
                         final boolean before = isUidForeground(uid);
                         mProcStatesCache.put(uid, procState);
@@ -370,9 +367,7 @@
                     } else {
                         mProcStatesCache.put(uid, procState);
                     }
-                }
-                boolean shouldAllowUpdate = isUidForeground(uid);
-                synchronized (mLock) {
+                    boolean shouldAllowUpdate = isUidForeground(uid);
                     ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap = mActiveSessions.get(uid);
                     if (tokenMap == null) {
                         return;
@@ -691,10 +686,10 @@
                     }
                 }
 
-                AppHintSession hs = new AppHintSession(callingUid, callingTgid, tids, token,
-                        halSessionPtr, durationNanos);
                 logPerformanceHintSessionAtom(callingUid, halSessionPtr, durationNanos, tids);
                 synchronized (mLock) {
+                    AppHintSession hs = new AppHintSession(callingUid, callingTgid, tids, token,
+                            halSessionPtr, durationNanos);
                     ArrayMap<IBinder, ArraySet<AppHintSession>> tokenMap =
                             mActiveSessions.get(callingUid);
                     if (tokenMap == null) {
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
index 40353a2..f1248a3 100644
--- a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
@@ -435,7 +435,8 @@
 
     @Override
     public boolean isTelephonyTimeZoneDetectionFeatureSupported() {
-        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+        return getConfigBoolean(com.android.internal.R.bool.config_enableTelephonyTimeZoneDetection)
+                && mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index ad54efc..84c37180 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -75,7 +75,7 @@
         IGNORED_ERROR_TOKEN(VibrationProto.IGNORED_ERROR_TOKEN),
         IGNORED_APP_OPS(VibrationProto.IGNORED_APP_OPS),
         IGNORED_BACKGROUND(VibrationProto.IGNORED_BACKGROUND),
-        IGNORED_UNKNOWN_VIBRATION(VibrationProto.IGNORED_UNKNOWN_VIBRATION),
+        IGNORED_MISSING_PERMISSION(VibrationProto.IGNORED_MISSING_PERMISSION),
         IGNORED_UNSUPPORTED(VibrationProto.IGNORED_UNSUPPORTED),
         IGNORED_FOR_EXTERNAL(VibrationProto.IGNORED_FOR_EXTERNAL),
         IGNORED_FOR_HIGHER_IMPORTANCE(VibrationProto.IGNORED_FOR_HIGHER_IMPORTANCE),
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 8281ac1..09c2493 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -436,26 +436,26 @@
             IBinder token, boolean fromIme) {
         HapticFeedbackVibrationProvider hapticVibrationProvider = getHapticVibrationProvider();
         if (hapticVibrationProvider == null) {
-            Slog.w(TAG, "performHapticFeedback; haptic vibration provider not ready.");
+            Slog.e(TAG, "performHapticFeedback; haptic vibration provider not ready.");
             return null;
         }
         if (hapticVibrationProvider.isRestrictedHapticFeedback(constant)
                 && !hasPermission(android.Manifest.permission.VIBRATE_SYSTEM_CONSTANTS)) {
-            Slog.w(TAG, "performHapticFeedback; no permission for effect " + constant);
+            Slog.w(TAG, "performHapticFeedback; no permission for system constant " + constant);
             return null;
         }
         VibrationEffect effect = hapticVibrationProvider.getVibrationForHapticFeedback(constant);
         if (effect == null) {
-            Slog.w(TAG, "performHapticFeedback; vibration absent for effect " + constant);
+            Slog.w(TAG, "performHapticFeedback; vibration absent for constant " + constant);
             return null;
         }
-        CombinedVibration combinedVibration = CombinedVibration.createParallel(effect);
+        CombinedVibration vib = CombinedVibration.createParallel(effect);
         VibrationAttributes attrs =
                 hapticVibrationProvider.getVibrationAttributesForHapticFeedback(
                         constant, /* bypassVibrationIntensitySetting= */ always, fromIme);
+        reason = "performHapticFeedback(constant=" + constant + "): " + reason;
         VibratorFrameworkStatsLogger.logPerformHapticsFeedbackIfKeyboard(uid, constant);
-        return vibrateWithoutPermissionCheck(uid, deviceId, opPkg, combinedVibration, attrs,
-                "performHapticFeedback: " + reason, token);
+        return vibrateWithoutPermissionCheck(uid, deviceId, opPkg, vib, attrs, reason, token);
     }
 
     /**
@@ -1951,39 +1951,34 @@
     /** Implementation of {@link IExternalVibratorService} to be triggered on external control. */
     @VisibleForTesting
     final class ExternalVibratorService extends IExternalVibratorService.Stub {
-        private static final ExternalVibrationScale SCALE_MUTE = new ExternalVibrationScale();
-
-        static {
-            SCALE_MUTE.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
-        }
 
         @Override
         public ExternalVibrationScale onExternalVibrationStart(ExternalVibration vib) {
-            if (!hasExternalControlCapability()) {
-                return SCALE_MUTE;
-            }
-            if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE,
-                    vib.getUid(), -1 /*owningUid*/, true /*exported*/)
-                    != PackageManager.PERMISSION_GRANTED) {
-                Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid()
-                        + " tried to play externally controlled vibration"
-                        + " without VIBRATE permission, ignoring.");
-                return SCALE_MUTE;
-            }
-
             // Create Vibration.Stats as close to the received request as possible, for tracking.
             ExternalVibrationHolder vibHolder = new ExternalVibrationHolder(vib);
-            VibrationAttributes attrs = fixupVibrationAttributes(vib.getVibrationAttributes(),
-                    /* effect= */ null);
-            if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
-                // Force update of user settings before checking if this vibration effect should
-                // be ignored or scaled.
-                mVibrationSettings.update();
-            }
-
+            // Mute the request until we run all the checks and accept the vibration.
+            vibHolder.scale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
             boolean alreadyUnderExternalControl = false;
             boolean waitForCompletion = false;
+
             synchronized (mLock) {
+                if (!hasExternalControlCapability()) {
+                    endVibrationAndWriteStatsLocked(vibHolder,
+                            new Vibration.EndInfo(Vibration.Status.IGNORED_UNSUPPORTED));
+                    return vibHolder.scale;
+                }
+
+                if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE,
+                        vib.getUid(), -1 /*owningUid*/, true /*exported*/)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid()
+                            + " tried to play externally controlled vibration"
+                            + " without VIBRATE permission, ignoring.");
+                    endVibrationAndWriteStatsLocked(vibHolder,
+                            new Vibration.EndInfo(Vibration.Status.IGNORED_MISSING_PERMISSION));
+                    return vibHolder.scale;
+                }
+
                 Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(
                         vibHolder.callerInfo);
 
@@ -2001,8 +1996,6 @@
                 }
 
                 if (vibrationEndInfo != null) {
-                    vibHolder.scale = SCALE_MUTE;
-                    // Failed to start the vibration, end it and report metrics right away.
                     endVibrationAndWriteStatsLocked(vibHolder, vibrationEndInfo);
                     return vibHolder.scale;
                 }
@@ -2040,6 +2033,15 @@
                                     vibHolder.callerInfo),
                             /* continueExternalControl= */ true);
                 }
+
+                VibrationAttributes attrs = fixupVibrationAttributes(vib.getVibrationAttributes(),
+                        /* effect= */ null);
+                if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
+                    // Force update of user settings before checking if this vibration effect should
+                    // be ignored or scaled.
+                    mVibrationSettings.update();
+                }
+
                 mCurrentExternalVibration = vibHolder;
                 vibHolder.linkToDeath();
                 vibHolder.scale.scaleLevel = mVibrationScaler.getScaleLevel(attrs.getUsage());
@@ -2055,8 +2057,10 @@
                         endExternalVibrateLocked(
                                 new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_CANCELLING),
                                 /* continueExternalControl= */ false);
+                        // Mute the request, vibration will be ignored.
+                        vibHolder.scale.scaleLevel = ExternalVibrationScale.ScaleLevel.SCALE_MUTE;
                     }
-                    return SCALE_MUTE;
+                    return vibHolder.scale;
                 }
             }
             if (!alreadyUnderExternalControl) {
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
index f6e0168..b19bc7d 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperCropper.java
@@ -99,15 +99,17 @@
 
     /**
      * Given the dimensions of the original wallpaper image, some optional suggested crops
-     * (either defined by the user, or coming from a backup), and whether the device is RTL,
+     * (either defined by the user, or coming from a backup), and whether the device has RTL layout,
      * generate a crop for the current display. This is done through the following process:
      * <ul>
-     *     <li> If no suggested crops are provided, center the full image on the display. </li>
+     *     <li> If no suggested crops are provided, in most cases render the full image left-aligned
+     *     (or right-aligned if RTL) and use any additional width for parallax up to
+     *     {@link #MAX_PARALLAX}. There are exceptions, see comments in "Case 1" of this function.
      *     <li> If there is a suggested crop the given displaySize, reuse the suggested crop and
-     *     adjust it using {@link #getAdjustedCrop}. </li>
+     *     adjust it using {@link #getAdjustedCrop}.
      *     <li> If there are suggested crops, but not for the orientation of the given displaySize,
      *     reuse one of the suggested crop for another orientation and adjust if using
-     *     {@link #getAdjustedCrop}. </li>
+     *     {@link #getAdjustedCrop}.
      * </ul>
      *
      * @param displaySize     The dimensions of the surface where we want to render the wallpaper
@@ -270,16 +272,12 @@
      * Adjust a given crop:
      * <ul>
      *     <li>If parallax = true, make sure we have a parallax of at most {@link #MAX_PARALLAX},
-     *     by removing content from the right (or left if RTL) if necessary.
-     *     </li>
+     *     by removing content from the right (or left if RTL layout) if necessary.
      *     <li>If parallax = false, make sure we do not have additional width for parallax. If we
      *     have additional width for parallax, remove half of the additional width on both sides.
-     *     </li>
      *     <li>Make sure the crop fills the screen, i.e. that the width/height ratio of the crop
-     *     is at least the width/height ratio of the screen. If it is less, add width to the crop
-     *     (if possible on both sides) to fill the screen. If not enough width available, remove
-     *     height to the crop.
-     *     </li>
+     *     is at least the width/height ratio of the screen. This is done accordingly to the
+     *     {@code mode} used, which can be either {@link #ADD}, {@link #REMOVE} or {@link #BALANCE}.
      * </ul>
      */
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index fe4522a..c5683f3 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -99,6 +99,7 @@
 import android.window.SizeConfigurationBuckets;
 import android.window.TransitionInfo;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.AssistUtils;
 import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.protolog.common.ProtoLog;
@@ -108,6 +109,9 @@
 import com.android.server.pm.pkg.AndroidPackage;
 import com.android.server.uri.GrantUri;
 import com.android.server.uri.NeededUriGrants;
+import com.android.server.utils.quota.Categorizer;
+import com.android.server.utils.quota.Category;
+import com.android.server.utils.quota.CountQuotaTracker;
 import com.android.server.vr.VrManagerInternal;
 
 /**
@@ -123,6 +127,13 @@
     private final ActivityTaskSupervisor mTaskSupervisor;
     private final Context mContext;
 
+    // Prevent malicious app abusing the Activity#setPictureInPictureParams API
+    @VisibleForTesting CountQuotaTracker mSetPipAspectRatioQuotaTracker;
+    // Limit to 60 times / minute
+    private static final int SET_PIP_ASPECT_RATIO_LIMIT = 60;
+    // The timeWindowMs here can not be smaller than QuotaTracker#MIN_WINDOW_SIZE_MS
+    private static final long SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS = 60_000;
+
     /** Wrapper around VoiceInteractionServiceManager. */
     private AssistUtils mAssistUtils;
 
@@ -1035,6 +1046,25 @@
                     + ": Current activity does not support picture-in-picture.");
         }
 
+        // Rate limit how frequent an app can request aspect ratio change via
+        // Activity#setPictureInPictureParams
+        final int userId = UserHandle.getCallingUserId();
+        if (mSetPipAspectRatioQuotaTracker == null) {
+            mSetPipAspectRatioQuotaTracker = new CountQuotaTracker(mContext,
+                    Categorizer.SINGLE_CATEGORIZER);
+            mSetPipAspectRatioQuotaTracker.setCountLimit(Category.SINGLE_CATEGORY,
+                    SET_PIP_ASPECT_RATIO_LIMIT, SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS);
+        }
+        if (r.pictureInPictureArgs.hasSetAspectRatio()
+                && params.hasSetAspectRatio()
+                && !r.pictureInPictureArgs.getAspectRatio().equals(
+                params.getAspectRatio())
+                && !mSetPipAspectRatioQuotaTracker.noteEvent(
+                userId, r.packageName, "setPipAspectRatio")) {
+            throw new IllegalStateException(caller
+                    + ": Too many PiP aspect ratio change requests from " + r.packageName);
+        }
+
         final float minAspectRatio = mContext.getResources().getFloat(
                 com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
         final float maxAspectRatio = mContext.getResources().getFloat(
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b3c43bc..fc05d17 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -1374,13 +1374,14 @@
 
             final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
 
+            final int userId = UserHandle.getCallingUserId();
             ActivityInfo aInfo = null;
             try {
                 List<ResolveInfo> resolves =
                         AppGlobals.getPackageManager().queryIntentActivities(
                                 intent, r.resolvedType,
                                 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS,
-                                UserHandle.getCallingUserId()).getList();
+                                userId).getList();
 
                 // Look for the original activity in the list...
                 final int N = resolves != null ? resolves.size() : 0;
@@ -1465,6 +1466,7 @@
                         .setRealCallingPid(-1)
                         .setRealCallingUid(r.launchedFromUid)
                         .setActivityOptions(options)
+                        .setUserId(userId)
                         .execute();
                 r.finishing = wasFinishing;
                 return res == ActivityManager.START_SUCCESS;
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index d0c6e15..4c53e0f 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -269,6 +269,8 @@
                                     customAppTransition.mBackgroundColor);
                         }
                     }
+                    infoBuilder.setLetterboxColor(currentActivity.mLetterboxUiController
+                            .getLetterboxBackgroundColor().toArgb());
                     removedWindowContainer = currentActivity;
                     prevTask = prevActivities.get(0).getTask();
                     backType = BackNavigationInfo.TYPE_CROSS_ACTIVITY;
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index 61f5679..f04b4af 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -114,6 +114,18 @@
             return RESULT_DONE;
         }
 
+        // TODO(b/336998072) - Find a better solution to this that makes use of the logic from
+        //  TaskLaunchParamsModifier. Put logic in common utils, return RESULT_CONTINUE, inherit
+        //  from parent class, etc.
+        if (outParams.mPreferredTaskDisplayArea == null && task.getRootTask() != null) {
+            appendLog("display-from-task=" + task.getRootTask().getDisplayId());
+            outParams.mPreferredTaskDisplayArea = task.getRootTask().getDisplayArea();
+        }
+
+        if (phase == PHASE_DISPLAY_AREA) {
+            return RESULT_DONE;
+        }
+
         if (!currentParams.mBounds.isEmpty()) {
             appendLog("currentParams has bounds set, not overriding");
             return RESULT_SKIP;
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index da1581e..683efde 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -1316,7 +1316,7 @@
         return shouldShowLetterboxUi;
     }
 
-    private Color getLetterboxBackgroundColor() {
+    Color getLetterboxBackgroundColor() {
         final WindowState w = mActivityRecord.findMainWindow();
         if (w == null || w.isLetterboxedForDisplayCutout()) {
             return Color.valueOf(Color.BLACK);
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index dd538de..312c4be 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -60,6 +60,7 @@
 import android.view.WindowInsets.Type;
 import android.window.PictureInPictureSurfaceTransaction;
 import android.window.TaskSnapshot;
+import android.window.WindowAnimationState;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.IResultReceiver;
@@ -371,6 +372,12 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
+
+        @Override
+        public void handOffAnimation(
+                RemoteAnimationTarget[] targets, WindowAnimationState[] states) {
+            // unused legacy implementation
+        }
     };
 
     /**
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 622a809..6003c1b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2477,6 +2477,7 @@
             final DisplayContent display = getChildAt(displayNdx);
             final boolean curResult = result;
             boolean[] resumedOnDisplay = new boolean[1];
+            final ActivityRecord topOfDisplay = display.topRunningActivity();
             display.forAllRootTasks(rootTask -> {
                 final ActivityRecord topRunningActivity = rootTask.topRunningActivity();
                 if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
@@ -2490,8 +2491,7 @@
                     resumedOnDisplay[0] |= curResult;
                     return;
                 }
-                if (topRunningActivity.isState(RESUMED)
-                        && topRunningActivity == rootTask.getDisplayArea().topRunningActivity()) {
+                if (topRunningActivity.isState(RESUMED) && topRunningActivity == topOfDisplay) {
                     // Kick off any lingering app transitions form the MoveTaskToFront operation,
                     // but only consider the top activity on that display.
                     rootTask.executeAppTransition(targetOptions);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index f23a440..9a7f87d 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -199,6 +199,7 @@
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.AppTimeTracker;
 import com.android.server.uri.NeededUriGrants;
+import com.android.window.flags.Flags;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -3363,7 +3364,8 @@
         // If true, we want to get the Dimmer from the level above since we don't want to animate
         // the dim with the Task.
         if (!isRootTask() || (Dimmer.DIMMER_REFACTOR && isTranslucentAndVisible())
-                || isTranslucent(null)) {
+                || (Flags.getDimmerOnClosing() ? isTranslucentForTransition()
+                                                : isTranslucent(null))) {
             return super.getDimmer();
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index de7c0eb..616ab88 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -349,6 +349,7 @@
 import com.android.server.DisplayThread;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
+import com.android.server.SystemConfig;
 import com.android.server.UiThread;
 import com.android.server.Watchdog;
 import com.android.server.input.InputManagerService;
@@ -454,13 +455,12 @@
     /**
      * Use WMShell for app transition.
      */
-    public static final String ENABLE_SHELL_TRANSITIONS = "persist.wm.debug.shell_transit";
+    private static final String ENABLE_SHELL_TRANSITIONS = "persist.wm.debug.shell_transit";
 
     /**
      * @see #ENABLE_SHELL_TRANSITIONS
      */
-    public static final boolean sEnableShellTransitions =
-            SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, true);
+    public static final boolean sEnableShellTransitions = getShellTransitEnabled();
 
     /**
      * Allows a fullscreen windowing mode activity to launch in its desired orientation directly
@@ -10230,4 +10230,13 @@
             }
         }
     }
+
+    private static boolean getShellTransitEnabled() {
+        android.content.pm.FeatureInfo autoFeature = SystemConfig.getInstance()
+                .getAvailableFeatures().get(PackageManager.FEATURE_AUTOMOTIVE);
+        if (autoFeature != null && autoFeature.version >= 0) {
+            return SystemProperties.getBoolean(ENABLE_SHELL_TRANSITIONS, true);
+        }
+        return true;
+    }
 }
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 736b051..25c5db1 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -34,3 +34,6 @@
 
 # Bug component : 158088 = per-file *AnrTimer*
 per-file *AnrTimer* = file:/PERFORMANCE_OWNERS
+
+# HintManagerService
+per-file com_android_server_hint_HintManagerService.cpp = file:/ADPF_OWNERS
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 553f721..80bf5b9 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -143,7 +143,6 @@
     jmethodID getTouchCalibrationForInputDevice;
     jmethodID notifyDropWindow;
     jmethodID getParentSurfaceForPointers;
-    jmethodID getPackageUid;
 } gServiceClassInfo;
 
 static struct {
@@ -364,7 +363,6 @@
     void notifyDropWindow(const sp<IBinder>& token, float x, float y) override;
     void notifyDeviceInteraction(int32_t deviceId, nsecs_t timestamp,
                                  const std::set<gui::Uid>& uids) override;
-    gui::Uid getPackageUid(std::string package) override;
 
     /* --- PointerControllerPolicyInterface implementation --- */
 
@@ -1126,21 +1124,6 @@
     mInputManager->getMetricsCollector().notifyDeviceInteraction(deviceId, timestamp, uids);
 }
 
-gui::Uid NativeInputManager::getPackageUid(std::string package) {
-    ATRACE_CALL();
-    JNIEnv* env = jniEnv();
-    ScopedLocalFrame localFrame(env);
-
-    ScopedLocalRef<jstring> javaPackage(env, env->NewStringUTF(package.c_str()));
-    const jint uid =
-            env->CallIntMethod(mServiceObj, gServiceClassInfo.getPackageUid, javaPackage.get());
-    if (checkAndClearExceptionFromCallback(env, "getPackageUid")) {
-        LOG(FATAL) << __func__ << ": Failed to get UID for package: " << package;
-    }
-
-    return gui::Uid{static_cast<uint32_t>(uid)};
-}
-
 void NativeInputManager::notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
                                            InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
                                            const std::vector<float>& values) {
@@ -3139,8 +3122,6 @@
     GET_METHOD_ID(gServiceClassInfo.getParentSurfaceForPointers, clazz,
                   "getParentSurfaceForPointers", "(I)J");
 
-    GET_METHOD_ID(gServiceClassInfo.getPackageUid, clazz, "getPackageUid", "(Ljava/lang/String;)I");
-
     // InputDevice
 
     FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice");
diff --git a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/testing/TestActivity.java b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/testing/TestActivity.java
index 73b4501..37b05ff 100644
--- a/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/testing/TestActivity.java
+++ b/services/tests/InputMethodSystemServerTests/test-apps/SimpleTestIme/src/com/android/apps/inputmethod/simpleime/testing/TestActivity.java
@@ -77,6 +77,7 @@
         mEditText = new EditText(this);
         mEditText.setContentDescription("Input box");
         rootView.addView(mEditText, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
+        rootView.setFitsSystemWindows(true);
         setContentView(rootView);
         mEditText.requestFocus();
         sLastCreatedInstance = new WeakReference<>(this);
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
index 8ad557c..89b4aea 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -1008,6 +1008,25 @@
     }
 
     @Test
+    public void testWriteReadPendingRestore() {
+        Settings settings = makeSettings();
+        PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1);
+        packageSetting.setAppId(Process.FIRST_APPLICATION_UID);
+        packageSetting.setPkg(PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed()
+                .setUid(packageSetting.getAppId())
+                .hideAsFinal());
+
+        packageSetting.setPendingRestore(true);
+        settings.mPackages.put(PACKAGE_NAME_1, packageSetting);
+
+        settings.writeLPr(computer, /*sync=*/true);
+        settings.mPackages.clear();
+
+        assertThat(settings.readLPw(computer, createFakeUsers()), is(true));
+        assertThat(settings.getPackageLPr(PACKAGE_NAME_1).isPendingRestore(), is(true));
+    }
+
+    @Test
     public void testWriteReadArchiveState() {
         Settings settings = makeSettings();
         PackageSetting packageSetting = createPackageSetting(PACKAGE_NAME_1);
diff --git a/services/tests/dreamservicetests/Android.bp b/services/tests/dreamservicetests/Android.bp
index 86b3a6c..6369d45 100644
--- a/services/tests/dreamservicetests/Android.bp
+++ b/services/tests/dreamservicetests/Android.bp
@@ -18,7 +18,9 @@
         "mockito-target-minus-junit4",
         "services.core",
         "mockingservicestests-utils-mockito",
+        "platform-test-annotations",
         "servicestests-utils",
+        "testables",
     ],
 
     defaults: [
diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java
index 293ab7b..23314cd 100644
--- a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java
+++ b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamServiceTest.java
@@ -19,17 +19,26 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
 
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
+import android.os.Looper;
+import android.platform.test.annotations.EnableFlags;
 import android.service.dreams.DreamService;
+import android.service.dreams.Flags;
+import android.service.dreams.IDreamOverlayCallback;
+import android.testing.TestableLooper;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -38,6 +47,18 @@
 public class DreamServiceTest {
     private static final String TEST_PACKAGE_NAME = "com.android.frameworks.dreamservicetests";
 
+    private TestableLooper mTestableLooper;
+
+    @Before
+    public void setup() throws Exception {
+        mTestableLooper = new TestableLooper(Looper.getMainLooper());
+    }
+
+    @After
+    public void tearDown() {
+        mTestableLooper.destroy();
+    }
+
     @Test
     public void testMetadataParsing() throws PackageManager.NameNotFoundException {
         final String testDreamClassName = "com.android.server.dreams.TestDreamService";
@@ -70,4 +91,76 @@
                 PackageManager.ComponentInfoFlags.of(PackageManager.GET_META_DATA));
         return DreamService.getDreamMetadata(context, si);
     }
+
+    /**
+     * Verifies progressing a {@link DreamService} to creation
+     */
+    @Test
+    public void testCreate() throws Exception {
+        final TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+                .setShouldShowComplications(true)
+                .build();
+        assertTrue(environment.advance(TestDreamEnvironment.DREAM_STATE_CREATE));
+    }
+
+    /**
+     * Verifies progressing a {@link DreamService}  to binding
+     */
+    @Test
+    public void testBind() throws Exception {
+        final TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+                .setShouldShowComplications(true)
+                .build();
+        assertTrue(environment.advance(TestDreamEnvironment.DREAM_STATE_BIND));
+    }
+
+    /**
+     * Verifies progressing a {@link DreamService} through
+     * {@link android.service.dreams.DreamActivity} creation.
+     */
+    @Test
+    public void testDreamActivityCreate() throws Exception {
+        final TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+                .setShouldShowComplications(true)
+                .build();
+        assertTrue(environment.advance(TestDreamEnvironment.DREAM_STATE_DREAM_ACTIVITY_CREATED));
+    }
+
+    /**
+     * Verifies progressing a {@link DreamService} through starting.
+     */
+    @Test
+    public void testStart() throws Exception {
+        final TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+                .setShouldShowComplications(true)
+                .build();
+        assertTrue(environment.advance(TestDreamEnvironment.DREAM_STATE_STARTED));
+    }
+
+    /**
+     * Verifies progressing a {@link DreamService} through waking.
+     */
+    @Test
+    public void testWake() throws Exception {
+        final TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+                .setShouldShowComplications(true)
+                .build();
+        assertTrue(environment.advance(TestDreamEnvironment.DREAM_STATE_WOKEN));
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_DREAM_WAKE_REDIRECT)
+    public void testRedirect() throws Exception {
+        TestDreamEnvironment environment = new TestDreamEnvironment.Builder(mTestableLooper)
+                .setDreamOverlayPresent(true)
+                .setShouldShowComplications(true)
+                .build();
+
+        environment.advance(TestDreamEnvironment.DREAM_STATE_STARTED);
+        final IDreamOverlayCallback overlayCallback = environment.getDreamOverlayCallback();
+        overlayCallback.onRedirectWake(true);
+        environment.resetClientInvocations();
+        environment.advance(TestDreamEnvironment.DREAM_STATE_WOKEN);
+        verify(environment.getDreamOverlayClient()).onWakeRequested();
+    }
 }
diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java
new file mode 100644
index 0000000..ef85ba5
--- /dev/null
+++ b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.dreams;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.description;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.IntDef;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IRemoteCallback;
+import android.os.Looper;
+import android.os.RemoteException;
+import android.service.dreams.DreamActivity;
+import android.service.dreams.DreamOverlayConnectionHandler;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
+import android.service.dreams.IDreamOverlayCallback;
+import android.service.dreams.IDreamOverlayClient;
+import android.service.dreams.IDreamService;
+import android.testing.TestableLooper;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowInsetsController;
+import android.view.WindowManager;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.function.Consumer;
+
+
+/**
+ * {@link TestDreamEnvironment} sets up entire testing environment around a dream service, allowing
+ * bring-up and interaction around the dream.
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class TestDreamEnvironment {
+    private static final String FAKE_DREAM_PACKAGE_NAME = "com.foo.bar";
+    private static final ComponentName FAKE_DREAM_OVERLAY_COMPONENT =
+            ComponentName.createRelative(FAKE_DREAM_PACKAGE_NAME, ".OverlayComponent");
+    private static final String FAKE_DREAM_SETTINGS_ACTIVITY = ".SettingsActivity";
+    private static final ComponentName FAKE_DREAM_ACTIVITY_COMPONENT =
+            ComponentName.createRelative(FAKE_DREAM_PACKAGE_NAME, ".DreamActivity");
+    private static final ComponentName FAKE_DREAM_COMPONENT =
+            ComponentName.createRelative(FAKE_DREAM_PACKAGE_NAME, ".DreamService");
+
+    /** Initial state when creating a test environment */
+    public static final int DREAM_STATE_INIT = 0;
+
+    /** State where the dream has been created */
+    public static final int DREAM_STATE_CREATE = 1;
+
+    /** State where the dream has been bound to */
+    public static final int DREAM_STATE_BIND = 2;
+
+    /** State where the dream activity has been created and signaled back to the dream */
+    public static final int DREAM_STATE_DREAM_ACTIVITY_CREATED = 3;
+
+
+    /** State where the dream has started after being attached */
+    public static final int DREAM_STATE_STARTED = 4;
+
+    /** State where the dream has been woken */
+    public static final int DREAM_STATE_WOKEN = 5;
+
+
+    @IntDef(prefix = { "DREAM_STATE_" }, value = {
+            DREAM_STATE_INIT,
+            DREAM_STATE_CREATE,
+            DREAM_STATE_BIND,
+            DREAM_STATE_DREAM_ACTIVITY_CREATED,
+            DREAM_STATE_STARTED,
+            DREAM_STATE_WOKEN,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DreamState{}
+
+    /**
+     * A convenience builder for assembling a {@link TestDreamEnvironment}.
+     */
+    public static class Builder {
+        private final TestableLooper mLooper;
+        private boolean mShouldShowComplications;
+        private boolean mOverlayPresent;
+        private boolean mWindowless;
+
+        public Builder(TestableLooper looper) {
+            mLooper = looper;
+        }
+
+        /**
+         * Sets whether the dream should show complications.
+         * @param show {@code true} for showing complications, {@code false} otherwise.
+         * @return The updated {@link Builder}.
+         */
+        public Builder setShouldShowComplications(boolean show) {
+            mShouldShowComplications = show;
+            return this;
+        }
+
+        /**
+         * Sets whether a dream overlay is present
+         * @param present {@code true} if the overlay is present, {@code false} otherwise.
+         */
+        public Builder setDreamOverlayPresent(boolean present) {
+            mOverlayPresent = present;
+            return this;
+        }
+
+        /**
+         * Sets whether the dream should be windowless
+         */
+        public Builder setWindowless(boolean windowless) {
+            mWindowless = windowless;
+            return this;
+        }
+
+        /**
+         * Builds the a {@link TestDreamEnvironment} based on the builder.
+         */
+        public TestDreamEnvironment build() throws Exception {
+            return new TestDreamEnvironment(mLooper, mShouldShowComplications,
+                    mOverlayPresent, mWindowless);
+        }
+    }
+
+    private static class TestInjector implements DreamService.Injector {
+        @Mock
+        private Resources mResources;
+
+        @Mock
+        private PackageManager mPackageManager;
+
+        @Mock
+        private TypedArray mAttributes;
+
+        @Mock
+        private ServiceInfo mServiceInfo;
+
+        private final Handler mHandler;
+        private final IDreamManager mDreamManager;
+        private final DreamOverlayConnectionHandler mDreamOverlayConnectionHandler;
+
+        TestInjector(Looper looper,
+                IDreamManager dreamManager,
+                DreamOverlayConnectionHandler dreamOverlayConnectionHandler,
+                boolean shouldShowComplications) {
+            MockitoAnnotations.initMocks(this);
+            mHandler = new Handler(looper);
+            mDreamManager = dreamManager;
+            mDreamOverlayConnectionHandler = dreamOverlayConnectionHandler;
+            mServiceInfo.packageName = FAKE_DREAM_PACKAGE_NAME;
+            when(mAttributes.getBoolean(eq(R.styleable.Dream_showClockAndComplications),
+                    anyBoolean()))
+                    .thenReturn(shouldShowComplications);
+            when(mAttributes.getDrawable(eq(com.android.internal.R.styleable.Dream_previewImage)))
+                    .thenReturn(mock(Drawable.class));
+            when(mAttributes.getString(eq(com.android.internal.R.styleable.Dream_settingsActivity)))
+                    .thenReturn(FAKE_DREAM_SETTINGS_ACTIVITY);
+            when(mPackageManager.extractPackageItemInfoAttributes(any(), any(), any(), any()))
+                    .thenReturn(mAttributes);
+        }
+        @Override
+        public void init(Context context) {
+        }
+
+        @Override
+        public DreamOverlayConnectionHandler createOverlayConnection(
+                ComponentName overlayComponent) {
+            return mDreamOverlayConnectionHandler;
+        }
+
+        @Override
+        public ComponentName getDreamActivityComponent() {
+            return FAKE_DREAM_ACTIVITY_COMPONENT;
+        }
+
+        @Override
+        public ComponentName getDreamComponent() {
+            return FAKE_DREAM_COMPONENT;
+        }
+
+        @Override
+        public String getDreamPackageName() {
+            return FAKE_DREAM_PACKAGE_NAME;
+        }
+
+        @Override
+        public IDreamManager getDreamManager() {
+            return mDreamManager;
+        }
+
+        @Override
+        public ServiceInfo getServiceInfo() {
+            return mServiceInfo;
+        }
+
+        @Override
+        public Handler getHandler() {
+            return mHandler;
+        }
+
+        @Override
+        public PackageManager getPackageManager() {
+            return mPackageManager;
+        }
+
+        @Override
+        public Resources getResources() {
+            return mResources;
+        }
+    }
+
+    @Mock
+    private IDreamManager mDreamManager;
+
+    @Mock
+    private DreamOverlayConnectionHandler mDreamOverlayConnectionHandler;
+
+    @Mock
+    private DreamActivity mDreamActivity;
+
+    @Mock
+    private Window mActivityWindow;
+
+    @Mock
+    private View mDecorView;
+
+    @Mock
+    private IDreamOverlayClient mDreamOverlayClient;
+
+    private final TestableLooper mTestableLooper;
+    private final DreamService mService;
+    private final boolean mWindowless;
+
+    private IDreamService mDreamServiceWrapper;
+
+    private @DreamState int mCurrentDreamState = DREAM_STATE_INIT;
+
+    private IDreamOverlayCallback mDreamOverlayCallback;
+
+    private boolean mOverlayPresent;
+
+    public TestDreamEnvironment(
+            TestableLooper looper,
+            boolean shouldShowComplications,
+            boolean overlayPresent,
+            boolean windowless
+    ) {
+        MockitoAnnotations.initMocks(this);
+
+        mOverlayPresent = overlayPresent;
+        mWindowless = windowless;
+
+        mTestableLooper = looper;
+        final DreamService.Injector injector = new TestInjector(mTestableLooper.getLooper(),
+                mDreamManager, mDreamOverlayConnectionHandler, shouldShowComplications);
+
+        when(mDreamActivity.getWindow()).thenReturn(mActivityWindow);
+        when(mActivityWindow.getAttributes()).thenReturn(mock(WindowManager.LayoutParams.class));
+        when(mActivityWindow.getDecorView()).thenReturn(mDecorView);
+        when(mDreamOverlayConnectionHandler.bind()).thenReturn(true);
+
+        doAnswer((InvocationOnMock invocation) -> {
+            Consumer<IDreamOverlayClient> client =
+                    (Consumer<IDreamOverlayClient>) invocation.getArguments()[0];
+            client.accept(mDreamOverlayClient);
+            return null;
+        }).when(mDreamOverlayConnectionHandler).addConsumer(any());
+        when(mDecorView.getWindowInsetsController()).thenReturn(
+                mock(WindowInsetsController.class));
+
+        mService = new DreamService(injector);
+    }
+
+    /**
+     * Advances a dream to a given state, progressing through all previous states.
+     */
+    public boolean advance(@DreamState int state) throws Exception {
+        if (state <= mCurrentDreamState) {
+            return false;
+        }
+
+        do {
+            switch(++mCurrentDreamState) {
+                case DREAM_STATE_CREATE -> createDream();
+                case DREAM_STATE_BIND -> bindToDream();
+                case DREAM_STATE_DREAM_ACTIVITY_CREATED -> createDreamActivity();
+                case DREAM_STATE_STARTED -> startDream();
+                case DREAM_STATE_WOKEN -> wakeDream();
+            }
+        } while (mCurrentDreamState < state);
+
+        return true;
+    }
+
+    private void createDream() {
+        mService.onCreate();
+        mService.setWindowless(mWindowless);
+    }
+
+    private void bindToDream() {
+        final Intent intent = new Intent();
+
+        if (mOverlayPresent) {
+            DreamService.setDreamOverlayComponent(intent, FAKE_DREAM_OVERLAY_COMPONENT);
+        }
+
+        mDreamServiceWrapper = IDreamService.Stub.asInterface(mService.onBind(intent));
+
+        if (mOverlayPresent) {
+            // Ensure that the overlay has been bound by the dream.
+            verify(mDreamOverlayConnectionHandler,
+                    description("dream did not bind to the dream overlay")).bind();
+        }
+    }
+
+    private void createDreamActivity() throws RemoteException {
+        final IRemoteCallback callback = mock(IRemoteCallback.class);
+        mDreamServiceWrapper.attach(mock(IBinder.class), false, false, callback);
+        mTestableLooper.processAllMessages();
+
+        final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+        verify(mDreamManager,
+                description("dream manager was not informed to start the dream activity"))
+                .startDreamActivity(intentCaptor.capture());
+        final Intent intent = intentCaptor.getValue();
+
+        final DreamService.DreamActivityCallbacks dreamActivityCallbacks =
+                DreamActivity.getCallback(intent);
+
+        dreamActivityCallbacks.onActivityCreated(mDreamActivity);
+    }
+
+    private void startDream() throws RemoteException {
+        final ArgumentCaptor<View.OnAttachStateChangeListener> attachChangeListenerCaptor =
+                ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
+        verify(mDecorView,
+                description("dream did not add a listener to when the decor view is attached"))
+                .addOnAttachStateChangeListener(attachChangeListenerCaptor.capture());
+
+        resetClientInvocations();
+        attachChangeListenerCaptor.getValue().onViewAttachedToWindow(mDecorView);
+
+        if (mOverlayPresent) {
+            final ArgumentCaptor<IDreamOverlayCallback> overlayCallbackCaptor =
+                    ArgumentCaptor.forClass(IDreamOverlayCallback.class);
+            verify(mDreamOverlayClient, description("dream client not informed of dream start"))
+                    .startDream(any(), overlayCallbackCaptor.capture(), any(), anyBoolean());
+
+            mDreamOverlayCallback = overlayCallbackCaptor.getValue();
+        }
+    }
+
+    private void wakeDream() throws RemoteException {
+        mService.wakeUp();
+    }
+
+    /**
+     * Retrieves the dream overlay callback.
+     */
+    public IDreamOverlayCallback getDreamOverlayCallback() throws Exception {
+        advance(DREAM_STATE_STARTED);
+        return mDreamOverlayCallback;
+    }
+
+    /**
+     * Resets interactions with the dream overlay client.
+     */
+    public void resetClientInvocations() {
+        Mockito.clearInvocations(mDreamOverlayClient);
+    }
+
+    /**
+     * Retrieves the dream overlay client.
+     */
+    public IDreamOverlayClient getDreamOverlayClient() {
+        return mDreamOverlayClient;
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 9590783..cc69c1d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -245,9 +245,11 @@
         LocalServices.removeServiceForTest(PackageManagerInternal.class);
     }
 
+    @SuppressWarnings("GuardedBy")
     @After
     public void tearDown() {
         sService.mOomAdjuster.resetInternal();
+        sService.mOomAdjuster.mActiveUids.clear();
     }
 
     private static <T> void setFieldValue(Class clazz, Object obj, String fieldName, T val) {
@@ -2816,6 +2818,69 @@
                 SCHED_GROUP_DEFAULT);
     }
 
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testSetUidTempAllowlistState() {
+        final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+        final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+        setProcessesToLru(app, app2);
+
+        // App1 binds to app2 and gets temp allowlisted.
+        bindService(app2, app, null, null, 0, mock(IBinder.class));
+        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, true);
+
+        assertEquals(true, app.getUidRecord().isSetAllowListed());
+        assertEquals(true, app.mOptRecord.shouldNotFreeze());
+        assertEquals(true, app2.mOptRecord.shouldNotFreeze());
+
+        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, false);
+        assertEquals(false, app.getUidRecord().isSetAllowListed());
+        assertEquals(false, app.mOptRecord.shouldNotFreeze());
+        assertEquals(false, app2.mOptRecord.shouldNotFreeze());
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testSetUidTempAllowlistState_multipleAllowlistClients() {
+        final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+        final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+        final ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+                MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+        setProcessesToLru(app, app2, app3);
+
+        // App1 and app2 both bind to app3 and get temp allowlisted.
+        bindService(app3, app, null, null, 0, mock(IBinder.class));
+        bindService(app3, app2, null, null, 0, mock(IBinder.class));
+        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, true);
+        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP2_UID, true);
+
+        assertEquals(true, app.getUidRecord().isSetAllowListed());
+        assertEquals(true, app2.getUidRecord().isSetAllowListed());
+        assertEquals(true, app.mOptRecord.shouldNotFreeze());
+        assertEquals(true, app2.mOptRecord.shouldNotFreeze());
+        assertEquals(true, app3.mOptRecord.shouldNotFreeze());
+
+        // Remove app1 from allowlist.
+        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP_UID, false);
+        assertEquals(false, app.getUidRecord().isSetAllowListed());
+        assertEquals(true, app2.getUidRecord().isSetAllowListed());
+        assertEquals(false, app.mOptRecord.shouldNotFreeze());
+        assertEquals(true, app2.mOptRecord.shouldNotFreeze());
+        assertEquals(true, app3.mOptRecord.shouldNotFreeze());
+
+        // Now remove app2 from allowlist.
+        sService.mOomAdjuster.setUidTempAllowlistStateLSP(MOCKAPP2_UID, false);
+        assertEquals(false, app.getUidRecord().isSetAllowListed());
+        assertEquals(false, app2.getUidRecord().isSetAllowListed());
+        assertEquals(false, app.mOptRecord.shouldNotFreeze());
+        assertEquals(false, app2.mOptRecord.shouldNotFreeze());
+        assertEquals(false, app3.mOptRecord.shouldNotFreeze());
+    }
+
     private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
             String packageName, boolean hasShownUi) {
         return new ProcessRecordBuilder(pid, uid, processName, packageName).setHasShownUi(
@@ -3057,6 +3122,14 @@
                 receivers.addCurReceiver(mock(BroadcastRecord.class));
             }
             providers.setLastProviderTime(mLastProviderTime);
+
+            UidRecord uidRec = sService.mOomAdjuster.mActiveUids.get(mUid);
+            if (uidRec == null) {
+                uidRec = new UidRecord(mUid, sService);
+                sService.mOomAdjuster.mActiveUids.put(mUid, uidRec);
+            }
+            uidRec.addProcess(app);
+            app.setUidRecord(uidRec);
             return app;
         }
     }
diff --git a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
index 67409a4..5c74a80 100644
--- a/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/powerservicetests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -1067,7 +1067,7 @@
             wakelockMap.remove((String) inv.getArguments()[1]);
             return null;
         }).when(mNotifierMock).onWakeLockReleased(anyInt(), anyString(), anyString(), anyInt(),
-                anyInt(), any(), any(), any());
+                anyInt(), any(), any(), any(), anyInt());
 
         //
         // TEST STARTS HERE
@@ -2777,7 +2777,7 @@
 
         mService.getBinderServiceInstance().releaseWakeLock(token, 0);
         verify(mNotifierMock).onWakeLockReleased(anyInt(), eq(tag), eq(packageName), anyInt(),
-                anyInt(), any(), any(), same(callback));
+                anyInt(), any(), any(), same(callback), anyInt());
     }
 
     /**
@@ -2796,8 +2796,8 @@
         when(callback1.asBinder()).thenReturn(callbackBinder1);
         mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
                 null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, callback1);
-        verify(mNotifierMock).onWakeLockAcquired(anyInt(), eq(tag), eq(packageName), anyInt(),
-                anyInt(), any(), any(), same(callback1));
+        verify(mNotifierMock).onWakeLockAcquired(anyInt(), eq(tag), eq(packageName),
+                anyInt(), anyInt(), any(), any(), same(callback1));
 
         final IWakeLockCallback callback2 = Mockito.mock(IWakeLockCallback.class);
         final IBinder callbackBinder2 = Mockito.mock(Binder.class);
@@ -2810,7 +2810,7 @@
 
         mService.getBinderServiceInstance().releaseWakeLock(token, 0);
         verify(mNotifierMock).onWakeLockReleased(anyInt(), eq(tag), eq(packageName), anyInt(),
-                anyInt(), any(), any(), same(callback2));
+                anyInt(), any(), any(), same(callback2), anyInt());
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java
index bfaf4959..f1b356a 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java
@@ -122,8 +122,6 @@
 
     @Before
     public void setup() throws RemoteException {
-        mSetFlagsRule.initAllFlagsToReleaseConfigDefault();
-
         MockitoAnnotations.initMocks(this);
         final Resources resources = InstrumentationRegistry.getContext().getResources();
 
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 7d90a8b..2b81d78 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
@@ -339,7 +339,6 @@
         LocalServices.removeServiceForTest(DisplayManagerInternal.class);
         LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
 
-        mSetFlagsRule.initAllFlagsToReleaseConfigDefault();
         mSetFlagsRule.enableFlags(com.android.input.flags.Flags.FLAG_ENABLE_POINTER_CHOREOGRAPHER);
 
         doNothing().when(mInputManagerInternalMock)
diff --git a/services/tests/servicestests/src/com/android/server/power/WakefulnessSessionObserverTest.java b/services/tests/servicestests/src/com/android/server/power/WakefulnessSessionObserverTest.java
new file mode 100644
index 0000000..698f094
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/WakefulnessSessionObserverTest.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.power;
+
+import static android.os.PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON;
+import static android.os.PowerManager.GO_TO_SLEEP_REASON_TIMEOUT;
+import static android.os.PowerManager.WAKE_REASON_POWER_BUTTON;
+
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_UNKNOWN;
+import static com.android.server.power.ScreenTimeoutOverridePolicy.RELEASE_REASON_USER_ACTIVITY_TOUCH;
+import static com.android.server.power.WakefulnessSessionObserver.OFF_REASON_POWER_BUTTON;
+import static com.android.server.power.WakefulnessSessionObserver.OVERRIDE_OUTCOME_CANCEL_POWER_BUTTON;
+import static com.android.server.power.WakefulnessSessionObserver.OVERRIDE_OUTCOME_CANCEL_USER_INTERACTION;
+import static com.android.server.power.WakefulnessSessionObserver.OVERRIDE_OUTCOME_TIMEOUT_SUCCESS;
+import static com.android.server.power.WakefulnessSessionObserver.OVERRIDE_OUTCOME_TIMEOUT_USER_INITIATED_REVERT;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.res.Resources;
+import android.os.PowerManager;
+import android.os.PowerManagerInternal;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.test.mock.MockContentResolver;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.testutils.OffsettableClock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class WakefulnessSessionObserverTest {
+    private static final int DEFAULT_SCREEN_OFF_TIMEOUT_MS = 30000;
+    private static final int OVERRIDE_SCREEN_OFF_TIMEOUT_MS = 15000;
+    private WakefulnessSessionObserver mWakefulnessSessionObserver;
+    private Context mContext;
+    private OffsettableClock mTestClock;
+    @Mock
+    private WakefulnessSessionObserver.WakefulnessSessionFrameworkStatsLogger
+            mWakefulnessSessionFrameworkStatsLogger;
+    private WakefulnessSessionObserver.Injector mInjector =
+            new WakefulnessSessionObserver.Injector() {
+                @Override
+                WakefulnessSessionObserver.WakefulnessSessionFrameworkStatsLogger
+                        getWakefulnessSessionFrameworkStatsLogger() {
+                    return mWakefulnessSessionFrameworkStatsLogger;
+                }
+                @Override
+                WakefulnessSessionObserver.Clock getClock() {
+                    return mTestClock::now;
+                }
+            };
+
+    @Before
+    public void setUp() {
+        mTestClock = new OffsettableClock.Stopped();
+
+        MockitoAnnotations.initMocks(this);
+        mContext = spy(new ContextWrapper(
+                InstrumentationRegistry.getInstrumentation().getTargetContext()));
+        doReturn(mContext).when(mContext).getApplicationContext();
+
+        final Resources res = spy(mContext.getResources());
+        doReturn(OVERRIDE_SCREEN_OFF_TIMEOUT_MS).when(res).getInteger(
+                com.android.internal.R.integer.config_screenTimeoutOverride);
+        when(mContext.getResources()).thenReturn(res);
+        FakeSettingsProvider.clearSettingsProvider();
+        MockContentResolver mockContentResolver = new MockContentResolver();
+        mockContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        when(mContext.getContentResolver()).thenReturn(mockContentResolver);
+        Settings.System.putIntForUser(mockContentResolver, Settings.System.SCREEN_OFF_TIMEOUT,
+                DEFAULT_SCREEN_OFF_TIMEOUT_MS, UserHandle.USER_CURRENT);
+
+        mWakefulnessSessionObserver = new WakefulnessSessionObserver(mContext, mInjector);
+    }
+
+    @After
+    public void tearDown() {
+        FakeSettingsProvider.clearSettingsProvider();
+    }
+
+    @Test
+    public void testOnUserActivity_updateActivity() {
+        int firstActivity = PowerManager.USER_ACTIVITY_EVENT_BUTTON;
+        long firstActivityTimestamp = mTestClock.now();
+        int powerGroupId = 1;
+        mWakefulnessSessionObserver.notifyUserActivity(
+                firstActivityTimestamp, powerGroupId, firstActivity);
+        assertThat(mWakefulnessSessionObserver.mPowerGroups.get(powerGroupId)
+                .mCurrentUserActivityEvent).isEqualTo(firstActivity);
+
+        int newActivity = PowerManager.USER_ACTIVITY_EVENT_ATTENTION;
+        advanceTime(10L);
+        long newActivityTimestamp = mTestClock.now();
+        mWakefulnessSessionObserver.notifyUserActivity(
+                newActivityTimestamp, powerGroupId, newActivity);
+        assertThat(mWakefulnessSessionObserver.mPowerGroups.get(powerGroupId)
+                .mCurrentUserActivityEvent).isEqualTo(newActivity);
+        assertThat(mWakefulnessSessionObserver.mPowerGroups.get(powerGroupId)
+                .mCurrentUserActivityTimestamp).isEqualTo(newActivityTimestamp);
+        assertThat(mWakefulnessSessionObserver.mPowerGroups.get(powerGroupId)
+                .mPrevUserActivityEvent).isEqualTo(firstActivity);
+        assertThat(mWakefulnessSessionObserver.mPowerGroups.get(powerGroupId)
+                .mPrevUserActivityTimestamp).isEqualTo(firstActivityTimestamp);
+
+        int otherPowerGroupId = 2;
+        mWakefulnessSessionObserver.notifyUserActivity(
+                firstActivityTimestamp, otherPowerGroupId, firstActivity);
+        assertThat(mWakefulnessSessionObserver.mPowerGroups.get(otherPowerGroupId)
+                .mCurrentUserActivityEvent).isEqualTo(firstActivity);
+        assertThat(mWakefulnessSessionObserver.mPowerGroups.get(otherPowerGroupId)
+                .mCurrentUserActivityTimestamp).isEqualTo(firstActivityTimestamp);
+    }
+
+    @Test
+    public void testOnWakeLockAcquired() {
+        mWakefulnessSessionObserver.onWakeLockAcquired(PowerManager.DOZE_WAKE_LOCK);
+        for (int idx = 0; idx < mWakefulnessSessionObserver.mPowerGroups.size(); idx++) {
+            assertThat(mWakefulnessSessionObserver.mPowerGroups.valueAt(idx).isInOverrideTimeout())
+                    .isFalse();
+        }
+
+        mWakefulnessSessionObserver.onWakeLockAcquired(
+                PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK);
+        for (int idx = 0; idx < mWakefulnessSessionObserver.mPowerGroups.size(); idx++) {
+            assertThat(mWakefulnessSessionObserver.mPowerGroups.valueAt(idx).isInOverrideTimeout())
+                    .isTrue();
+        }
+    }
+
+    @Test
+    public void testOnWakeLockReleased() {
+        mWakefulnessSessionObserver.onWakeLockReleased(
+                PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK, RELEASE_REASON_UNKNOWN);
+        for (int idx = 0; idx < mWakefulnessSessionObserver.mPowerGroups.size(); idx++) {
+            assertThat(mWakefulnessSessionObserver.mPowerGroups.valueAt(idx).isInOverrideTimeout())
+                    .isFalse();
+        }
+    }
+
+    @Test
+    public void testOnWakefulnessChangeStarted_onDozing_UserActivityAttention_OverrideTimeout() {
+        int powerGroupId = 1;
+        mWakefulnessSessionObserver.onWakefulnessChangeStarted(
+                powerGroupId,
+                PowerManagerInternal.WAKEFULNESS_AWAKE,
+                WAKE_REASON_POWER_BUTTON,
+                mTestClock.now());
+        mWakefulnessSessionObserver.notifyUserActivity(
+                mTestClock.now(), powerGroupId, PowerManager.USER_ACTIVITY_EVENT_ATTENTION);
+        mWakefulnessSessionObserver.onWakeLockAcquired(
+                PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK);
+        mWakefulnessSessionObserver.onWakefulnessChangeStarted(
+                powerGroupId,
+                PowerManagerInternal.WAKEFULNESS_DOZING,
+                GO_TO_SLEEP_REASON_TIMEOUT,
+                mTestClock.now());
+
+        verify(mWakefulnessSessionFrameworkStatsLogger)
+                .logTimeoutOverrideEvent(
+                        powerGroupId, // powerGroupId
+                        OVERRIDE_OUTCOME_TIMEOUT_SUCCESS, // overrideOutcome
+                        OVERRIDE_SCREEN_OFF_TIMEOUT_MS, // override timeout ms
+                        DEFAULT_SCREEN_OFF_TIMEOUT_MS); // default timeout ms
+    }
+
+    @Test
+    public void testOnWakefulnessChangeStarted_onDozing_UserActivityButton() {
+        advanceTime(5000L); // reset current timestamp for new test case
+        int powerGroupId = 2;
+        mWakefulnessSessionObserver.onWakefulnessChangeStarted(
+                powerGroupId,
+                PowerManagerInternal.WAKEFULNESS_AWAKE,
+                WAKE_REASON_POWER_BUTTON,
+                mTestClock.now());
+
+        int userActivity = PowerManager.USER_ACTIVITY_EVENT_DEVICE_STATE;
+        long userActivityTime = mTestClock.now();
+        mWakefulnessSessionObserver.notifyUserActivity(
+                userActivityTime, powerGroupId, userActivity);
+        long advancedTime = 10L;
+        advanceTime(advancedTime);
+        mWakefulnessSessionObserver.notifyUserActivity(
+                userActivityTime, powerGroupId, PowerManager.USER_ACTIVITY_EVENT_BUTTON);
+        mWakefulnessSessionObserver.onWakefulnessChangeStarted(
+                powerGroupId,
+                PowerManagerInternal.WAKEFULNESS_DOZING,
+                GO_TO_SLEEP_REASON_POWER_BUTTON,
+                mTestClock.now());
+
+        verify(mWakefulnessSessionFrameworkStatsLogger)
+                .logSessionEvent(
+                        powerGroupId, // powerGroupId
+                        OFF_REASON_POWER_BUTTON, // interactiveStateOffReason
+                        advancedTime, // interactiveStateOnDurationMs
+                        userActivity, // userActivity
+                        advancedTime,  // lastUserActivityEventDurationMs
+                        0); // reducedInteractiveStateOnDurationMs;
+
+        verify(mWakefulnessSessionFrameworkStatsLogger, never())
+                .logTimeoutOverrideEvent(anyInt(), anyInt(), anyInt(), anyInt());
+    }
+
+    @Test
+    public void testOnWakefulnessChangeStarted_onDozing_UserActivityButton_OverrideTimeout() {
+        int powerGroupId = 1;
+        mWakefulnessSessionObserver.onWakefulnessChangeStarted(
+                powerGroupId,
+                PowerManagerInternal.WAKEFULNESS_AWAKE,
+                WAKE_REASON_POWER_BUTTON,
+                mTestClock.now());
+        mWakefulnessSessionObserver.onWakeLockAcquired(
+                PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK);
+
+        int userActivity = PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY;
+        long userActivityTime = mTestClock.now();
+        mWakefulnessSessionObserver.notifyUserActivity(
+                userActivityTime, powerGroupId, userActivity);
+        long advancedTime = 10L;
+        advanceTime(advancedTime);
+        mWakefulnessSessionObserver.notifyUserActivity(
+                userActivityTime, powerGroupId, PowerManager.USER_ACTIVITY_EVENT_BUTTON);
+        mWakefulnessSessionObserver.onWakefulnessChangeStarted(
+                powerGroupId,
+                PowerManagerInternal.WAKEFULNESS_DOZING,
+                GO_TO_SLEEP_REASON_POWER_BUTTON,
+                mTestClock.now());
+
+        verify(mWakefulnessSessionFrameworkStatsLogger)
+                .logTimeoutOverrideEvent(
+                        powerGroupId, // powerGroupId
+                        OVERRIDE_OUTCOME_CANCEL_POWER_BUTTON, // overrideOutcome
+                        OVERRIDE_SCREEN_OFF_TIMEOUT_MS, // override timeout ms
+                        DEFAULT_SCREEN_OFF_TIMEOUT_MS); // default timeout ms
+
+        verify(mWakefulnessSessionFrameworkStatsLogger)
+                .logSessionEvent(
+                        powerGroupId, // powerGroupId
+                        OFF_REASON_POWER_BUTTON, // interactiveStateOffReason
+                        advancedTime, // interactiveStateOnDurationMs
+                        userActivity, // userActivity
+                        advancedTime,  // lastUserActivityEventDurationMs
+                        0); // reducedInteractiveStateOnDurationMs;
+    }
+
+    @Test
+    public void testOnWakefulnessChangeStarted_inTimeoutOverride_onAwake_After_onDozing() {
+        int powerGroupId = 1;
+        mWakefulnessSessionObserver.onWakeLockAcquired(
+                PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK);
+
+        mWakefulnessSessionObserver.onWakefulnessChangeStarted(
+                powerGroupId, PowerManagerInternal.WAKEFULNESS_DOZING,
+                GO_TO_SLEEP_REASON_TIMEOUT, mTestClock.now());
+        // awake after dozing
+        advanceTime(10L);
+        mWakefulnessSessionObserver.onWakefulnessChangeStarted(
+                powerGroupId, PowerManagerInternal.WAKEFULNESS_AWAKE,
+                WAKE_REASON_POWER_BUTTON, mTestClock.now());
+
+        verify(mWakefulnessSessionFrameworkStatsLogger)
+                .logTimeoutOverrideEvent(
+                        powerGroupId,  // powerGroupId
+                        OVERRIDE_OUTCOME_TIMEOUT_USER_INITIATED_REVERT, // overrideOutcome
+                        OVERRIDE_SCREEN_OFF_TIMEOUT_MS, // override timeout ms
+                        DEFAULT_SCREEN_OFF_TIMEOUT_MS); // default timeout ms
+    }
+
+    @Test
+    public void testOnWakeLockReleased_UserActivityTouch() {
+        int powerGroupId = 0;
+        mWakefulnessSessionObserver.onWakeLockAcquired(
+                PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK);
+        advanceTime(5000L);
+        mWakefulnessSessionObserver.onWakeLockReleased(
+                PowerManager.SCREEN_TIMEOUT_OVERRIDE_WAKE_LOCK,
+                RELEASE_REASON_USER_ACTIVITY_TOUCH);
+
+        verify(mWakefulnessSessionFrameworkStatsLogger)
+                .logTimeoutOverrideEvent(
+                        powerGroupId, // powerGroupId
+                        OVERRIDE_OUTCOME_CANCEL_USER_INTERACTION, // overrideOutcome
+                        OVERRIDE_SCREEN_OFF_TIMEOUT_MS, // override timeout ms
+                        DEFAULT_SCREEN_OFF_TIMEOUT_MS); // default timeout ms
+    }
+
+    private void advanceTime(long timeMs) {
+        mTestClock.fastForward(timeMs);
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index a911131..ab8c53c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -53,6 +53,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.res.Resources;
 import android.os.Bundle;
+import android.os.Looper;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
@@ -531,7 +532,7 @@
         Task task = createTopTaskWithActivity();
         WindowState appWindow = task.getTopVisibleAppMainWindow();
         WindowOnBackInvokedDispatcher dispatcher =
-                new WindowOnBackInvokedDispatcher(context);
+                new WindowOnBackInvokedDispatcher(context, Looper.getMainLooper());
         spyOn(appWindow.mSession);
         doAnswer(invocation -> {
             appWindow.setOnBackInvokedCallbackInfo(invocation.getArgument(1));
@@ -742,6 +743,10 @@
             @Override
             public void onBackInvoked() {
             }
+
+            @Override
+            public void setTriggerBack(boolean triggerBack) {
+            }
         };
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java
index 073b551..57118f2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentDeferredUpdateTests.java
@@ -65,9 +65,6 @@
 
     @Override
     protected void onBeforeSystemServicesCreated() {
-        // Set other flags to their default values
-        mSetFlagsRule.initAllFlagsToReleaseConfigDefault();
-
         mSetFlagsRule.enableFlags(Flags.FLAG_DEFER_DISPLAY_UPDATES);
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index dcf3dad..7756edd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -832,7 +832,8 @@
 
         // Assume the task is at the topmost position
         assertFalse(rootTask.isTopRootTaskInDisplayArea());
-        doReturn(taskDisplayArea.getHomeActivity()).when(taskDisplayArea).topRunningActivity();
+        doReturn(taskDisplayArea.getHomeActivity()).when(taskDisplayArea).topRunningActivity(
+                anyBoolean());
 
         // Use the task as target to resume.
         mRootWindowContainer.resumeFocusedTasksTopActivities();
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 43b424f..fb854c5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -1235,6 +1235,12 @@
         assertNotNull(o.mInfo);
         assertNotNull(o.mInfo.pictureInPictureParams);
 
+        // Bypass the quota check, which causes NPE in current test setup.
+        if (mWm.mAtmService.mActivityClientController.mSetPipAspectRatioQuotaTracker != null) {
+            mWm.mAtmService.mActivityClientController.mSetPipAspectRatioQuotaTracker
+                    .setEnabled(false);
+        }
+
         final PictureInPictureParams p2 = new PictureInPictureParams.Builder()
                 .setAspectRatio(new Rational(3, 4)).build();
         mWm.mAtmService.mActivityClientController.setPictureInPictureParams(record.token, p2);
diff --git a/tests/MultiDeviceInput/src/test/multideviceinput/DrawingView.kt b/tests/MultiDeviceInput/src/test/multideviceinput/DrawingView.kt
index b5bd9ca..8bc2f97 100644
--- a/tests/MultiDeviceInput/src/test/multideviceinput/DrawingView.kt
+++ b/tests/MultiDeviceInput/src/test/multideviceinput/DrawingView.kt
@@ -21,8 +21,13 @@
 import android.graphics.Color
 import android.graphics.Paint
 import android.util.AttributeSet
+import android.view.InputDevice
+import android.view.InputDevice.SOURCE_MOUSE
 import android.view.InputDevice.SOURCE_STYLUS
+import android.view.InputDevice.SOURCE_TOUCHSCREEN
+import android.view.InputDevice.SOURCE_TOUCHPAD
 import android.view.MotionEvent
+import android.view.MotionEvent.ACTION_CANCEL
 import android.view.MotionEvent.ACTION_DOWN
 import android.view.MotionEvent.ACTION_HOVER_EXIT
 import android.view.MotionEvent.ACTION_UP
@@ -56,8 +61,8 @@
 }
 
 private fun drawCircle(canvas: Canvas, event: MotionEvent, paint: Paint, radius: Float) {
-    val x = event.getX()
-    val y = event.getY()
+    val x = event.x
+    val y = event.y
     canvas.drawCircle(x, y, radius, paint)
 }
 
@@ -110,44 +115,72 @@
     private val scaleGestureDetector = ScaleGestureDetector(context, scaleGestureListener, null)
 
     private var touchPaint = Paint()
+    private var touchpadPaint = Paint()
     private var stylusPaint = Paint()
+    private var mousePaint = Paint()
+    private var drawingTabletPaint = Paint()
 
     private fun init() {
         touchPaint.color = Color.RED
-        touchPaint.setStrokeWidth(5f)
+        touchPaint.strokeWidth = 5f
+        touchpadPaint.color = Color.BLACK
+        touchpadPaint.strokeWidth = 5f
         stylusPaint.color = Color.YELLOW
-        stylusPaint.setStrokeWidth(5f)
-
+        stylusPaint.strokeWidth = 5f
+        mousePaint.color = Color.BLUE
+        mousePaint.strokeWidth = 5f
+        drawingTabletPaint.color = Color.GREEN
+        drawingTabletPaint.strokeWidth = 5f
         setOnHoverListener { _, event -> processHoverEvent(event); true }
     }
 
+    private fun resolvePaint(event: MotionEvent): Paint? {
+        val inputDevice = InputDevice.getDevice(event.deviceId)
+        val isTouchpadDevice = inputDevice != null && inputDevice.supportsSource(SOURCE_TOUCHPAD)
+        return if (event.isFromSource(SOURCE_STYLUS or SOURCE_MOUSE)) {
+            // External stylus / drawing tablet
+            drawingTabletPaint
+        } else if (event.isFromSource(SOURCE_TOUCHSCREEN) && !event.isFromSource(SOURCE_STYLUS)) {
+            // Touchscreen event
+            touchPaint
+        } else if (event.isFromSource(SOURCE_MOUSE) &&
+            (event.isFromSource(SOURCE_TOUCHPAD) || isTouchpadDevice)) {
+            // Touchpad event
+            touchpadPaint
+        } else if (event.isFromSource(SOURCE_MOUSE)) {
+            // Mouse event
+            mousePaint
+        } else if (event.isFromSource(SOURCE_STYLUS)) {
+            // Stylus event
+            stylusPaint
+        } else {
+            // Drop the event
+            null
+        }
+    }
+
     private fun processTouchEvent(event: MotionEvent) {
         scaleGestureDetector.onTouchEvent(event)
         if (event.actionMasked == ACTION_DOWN) {
             touchEvents.remove(event.deviceId)
             myState?.state = PointerState.DOWN
-        } else if (event.actionMasked == ACTION_UP) {
+        } else if (event.actionMasked == ACTION_UP || event.actionMasked == ACTION_CANCEL) {
             myState?.state = PointerState.NONE
         }
-        var vec = touchEvents.getOrPut(event.deviceId) { Vector<Pair<MotionEvent, Paint>>() }
-
-        val paint = if (event.isFromSource(SOURCE_STYLUS)) {
+        val paint = resolvePaint(event)
+        if (paint != null) {
+            val vec = touchEvents.getOrPut(event.deviceId) { Vector<Pair<MotionEvent, Paint>>() }
             val size = myState?.lineSize ?: 5f
-            stylusPaint.setStrokeWidth(size)
-            Paint(stylusPaint)
-        } else {
-            val size = myState?.lineSize ?: 5f
-            touchPaint.setStrokeWidth(size)
-            Paint(touchPaint)
+            paint.strokeWidth = size
+            vec.add(Pair(MotionEvent.obtain(event), Paint(paint)))
+            invalidate()
         }
-        vec.add(Pair(MotionEvent.obtain(event), paint))
-        invalidate()
     }
 
     private fun processHoverEvent(event: MotionEvent) {
         hoverEvents.remove(event.deviceId)
-        if (event.getActionMasked() != ACTION_HOVER_EXIT) {
-            hoverEvents.put(event.deviceId, MotionEvent.obtain(event))
+        if (event.actionMasked != ACTION_HOVER_EXIT) {
+            hoverEvents[event.deviceId] = MotionEvent.obtain(event)
             myState?.state = PointerState.HOVER
         } else {
             myState?.state = PointerState.NONE
@@ -155,7 +188,7 @@
         invalidate()
     }
 
-    public override fun onTouchEvent(event: MotionEvent): Boolean {
+    override fun onTouchEvent(event: MotionEvent): Boolean {
         processTouchEvent(event)
         return true
     }
@@ -171,12 +204,10 @@
         }
         // Draw hovers
         for ((_, event) in hoverEvents ) {
-            if (event.isFromSource(SOURCE_STYLUS)) {
+            val paint = resolvePaint(event)
+            if (paint != null) {
                 val size = myState?.circleSize ?: 20f
-                drawCircle(canvas, event, stylusPaint, size)
-            } else {
-                val size = myState?.circleSize ?: 20f
-                drawCircle(canvas, event, touchPaint, size)
+                drawCircle(canvas, event, paint, size)
             }
         }
     }
diff --git a/tests/testables/src/android/testing/ViewUtils.java b/tests/testables/src/android/testing/ViewUtils.java
index 80c2e8d..0fad79d 100644
--- a/tests/testables/src/android/testing/ViewUtils.java
+++ b/tests/testables/src/android/testing/ViewUtils.java
@@ -31,13 +31,20 @@
      * This is currently done by adding the view to a window.
      */
     public static void attachView(View view) {
+        attachView(view, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+    }
+
+    /**
+     * Causes the view (and its children) to have {@link View#onAttachedToWindow()} called.
+     *
+     * This is currently done by adding the view to a window.
+     */
+    public static void attachView(View view, int width, int height) {
         // Make sure hardware acceleration isn't turned on.
         view.getContext().getApplicationInfo().flags &=
                 ~(ApplicationInfo.FLAG_HARDWARE_ACCELERATED);
-        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
-                LayoutParams.TYPE_APPLICATION_OVERLAY,
-                0, PixelFormat.TRANSLUCENT);
+        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height,
+                LayoutParams.TYPE_APPLICATION_OVERLAY, 0, PixelFormat.TRANSLUCENT);
         view.getContext().getSystemService(WindowManager.class).addView(view, lp);
     }
 
diff --git a/tools/aapt/SdkConstants.h b/tools/aapt/SdkConstants.h
index e2c1614..ebb82ce 100644
--- a/tools/aapt/SdkConstants.h
+++ b/tools/aapt/SdkConstants.h
@@ -50,6 +50,7 @@
     SDK_S_V2 = 32,
     SDK_TIRAMISU = 33,
     SDK_UPSIDE_DOWN_CAKE = 34,
+    SDK_VANILLA_ICE_CREAM = 35,
     SDK_CUR_DEVELOPMENT = 10000,
 };
 
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index b4e2758..4c81939 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -227,56 +227,3 @@
         ],
     },
 }
-
-cc_genrule {
-    name: "aapt2_results",
-    srcs: [
-        ":aapt2_tests",
-        "integration-tests/CompileTest/**/*",
-        "integration-tests/CommandTests/**/*",
-        "integration-tests/ConvertTest/**/*",
-        "integration-tests/DumpTest/**/*",
-    ],
-    host_supported: true,
-    device_supported: false,
-    target: {
-        windows: {
-            compile_multilib: "64",
-        },
-    },
-    out: ["result.xml"],
-    cmd: "mkdir -p $(genDir)/integration-tests/CompileTest/ && " +
-        "cp $(locations integration-tests/CompileTest/**/*) $(genDir)/integration-tests/CompileTest/ && " +
-        "mkdir -p $(genDir)/integration-tests/CommandTests/ && " +
-        "cp $(locations integration-tests/CommandTests/**/*) $(genDir)/integration-tests/CompileTest/ && " +
-        "mkdir -p $(genDir)/integration-tests/ConvertTest/ && " +
-        "cp $(locations integration-tests/ConvertTest/**/*) $(genDir)/integration-tests/ConvertTest/ && " +
-        "mkdir -p $(genDir)/integration-tests/DumpTest/ && " +
-        "cp $(locations integration-tests/DumpTest/**/*) $(genDir)/integration-tests/DumpTest/ && " +
-        "cp $(locations :aapt2_tests) $(genDir)/ && " +
-        "$(genDir)/aapt2_tests " +
-        "--gtest_output=xml:$(out) " +
-        ">/dev/null 2>&1 ; true",
-    dist: {
-        targets: ["aapt2_run_host_unit_tests"],
-        dir: "gtest",
-        dest: "aapt2_host_unit_tests_result.xml",
-    },
-    arch: {
-        x86: {
-            dist: {
-                suffix: "_x86",
-            },
-        },
-        x86_64: {
-            dist: {
-                suffix: "_x86_64",
-            },
-        },
-    },
-}
-
-phony_rule {
-    name: "aapt2_run_host_unit_tests",
-    phony_deps: ["aapt2_results"],
-}
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index e47704ea..f131cc6 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -60,6 +60,7 @@
   SDK_S_V2 = 32,
   SDK_TIRAMISU = 33,
   SDK_UPSIDE_DOWN_CAKE = 34,
+  SDK_VANILLA_ICE_CREAM = 35,
   SDK_CUR_DEVELOPMENT = 10000,
 };
 
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 803dc28..2f432cc 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -85,9 +85,13 @@
 
         // Dump statistics, if specified.
         options.statsFile.ifSet {
-            PrintWriter(it).use { pw -> stats.dump(pw) }
+            PrintWriter(it).use { pw -> stats.dumpOverview(pw) }
             log.i("Dump file created at $it")
         }
+        options.apiListFile.ifSet {
+            PrintWriter(it).use { pw -> stats.dumpApis(pw) }
+            log.i("API list file created at $it")
+        }
     }
 
     /**
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
index 9ff798a..e192516 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -110,6 +110,8 @@
         var enableNonStubMethodCallDetection: SetOnce<Boolean> = SetOnce(false),
 
         var statsFile: SetOnce<String?> = SetOnce(null),
+
+        var apiListFile: SetOnce<String?> = SetOnce(null),
 ) {
     companion object {
 
@@ -255,6 +257,7 @@
                         "--debug-log" -> setLogFile(LogLevel.Debug, nextArg())
 
                         "--stats-file" -> ret.statsFile.setNextStringArg()
+                        "--supported-api-list-file" -> ret.apiListFile.setNextStringArg()
 
                         else -> throw ArgumentsException("Unknown option: $arg")
                     }
@@ -392,6 +395,7 @@
               enablePostTrace=$enablePostTrace,
               enableNonStubMethodCallDetection=$enableNonStubMethodCallDetection,
               statsFile=$statsFile,
+              apiListFile=$apiListFile,
             }
             """.trimIndent()
     }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt
index 50518e1..da61469 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt
@@ -29,8 +29,25 @@
 
     private val stats = mutableMapOf<String, Stats>()
 
-    fun onVisitPolicyForMethod(fullClassName: String, methodName: String, descriptor: String,
-                               policy: FilterPolicyWithReason, access: Int) {
+    data class Api(
+        val fullClassName: String,
+        val methodName: String,
+        val methodDesc: String,
+    )
+
+    private val apis = mutableListOf<Api>()
+
+    fun onVisitPolicyForMethod(
+        fullClassName: String,
+        methodName: String,
+        descriptor: String,
+        policy: FilterPolicyWithReason,
+        access: Int
+    ) {
+        if (policy.policy.isSupported) {
+            apis.add(Api(fullClassName, methodName, descriptor))
+        }
+
         // Ignore methods that aren't public
         if ((access and Opcodes.ACC_PUBLIC) == 0) return
         // Ignore methods that are abstract
@@ -39,7 +56,7 @@
         if (policy.isIgnoredForStats) return
 
         val packageName = resolvePackageName(fullClassName)
-        val className = resolveClassName(fullClassName)
+        val className = resolveOuterClassName(fullClassName)
 
         // Ignore methods for certain generated code
         if (className.endsWith("Proto")
@@ -60,11 +77,11 @@
         classStats.total += 1
     }
 
-    fun dump(pw: PrintWriter) {
+    fun dumpOverview(pw: PrintWriter) {
         pw.printf("PackageName,ClassName,SupportedMethods,TotalMethods\n")
-        stats.forEach { (packageName, packageStats) ->
+        stats.toSortedMap().forEach { (packageName, packageStats) ->
             if (packageStats.supported > 0) {
-                packageStats.children.forEach { (className, classStats) ->
+                packageStats.children.toSortedMap().forEach { (className, classStats) ->
                     pw.printf("%s,%s,%d,%d\n", packageName, className,
                             classStats.supported, classStats.total)
                 }
@@ -72,12 +89,26 @@
         }
     }
 
+    fun dumpApis(pw: PrintWriter) {
+        pw.printf("PackageName,ClassName,MethodName,MethodDesc\n")
+        apis.sortedWith(compareBy({ it.fullClassName }, { it.methodName }, { it.methodDesc }))
+            .forEach { api ->
+            pw.printf(
+                "%s,%s,%s,%s\n",
+                csvEscape(resolvePackageName(api.fullClassName)),
+                csvEscape(resolveClassName(api.fullClassName)),
+                csvEscape(api.methodName),
+                csvEscape(api.methodDesc),
+                )
+        }
+    }
+
     private fun resolvePackageName(fullClassName: String): String {
         val start = fullClassName.lastIndexOf('/')
         return fullClassName.substring(0, start).toHumanReadableClassName()
     }
 
-    private fun resolveClassName(fullClassName: String): String {
+    private fun resolveOuterClassName(fullClassName: String): String {
         val start = fullClassName.lastIndexOf('/')
         val end = fullClassName.indexOf('$')
         if (end == -1) {
@@ -86,4 +117,13 @@
             return fullClassName.substring(start + 1, end)
         }
     }
+
+    private fun resolveClassName(fullClassName: String): String {
+        val pos = fullClassName.lastIndexOf('/')
+        if (pos == -1) {
+            return fullClassName
+        } else {
+            return fullClassName.substring(pos + 1)
+        }
+    }
 }
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
index aa63d8d9..10179ee 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
@@ -89,3 +89,10 @@
         }
     }
 }
+
+/**
+ * Escape a string for a CSV field.
+ */
+fun csvEscape(value: String): String {
+    return "\"" + value.replace("\"", "\"\"") + "\""
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt
index 76bac92..16785d1 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/filters/AndroidHeuristicsFilter.kt
@@ -51,6 +51,8 @@
 }
 
 /**
+ * Effectively apply @RavenwoodKeepWholeClass to all classes with these names
+ *
  * @return if a given class "seems like" an feature flags class.
  */
 private fun ClassNodes.isFeatureFlagsClass(className: String): Boolean {
@@ -59,6 +61,7 @@
     return className.endsWith("/Flags")
             || className.endsWith("/FeatureFlags")
             || className.endsWith("/FeatureFlagsImpl")
+            || className.endsWith("/CustomFeatureFlags")
             || className.endsWith("/FakeFeatureFlagsImpl");
 }